Shiro入门-hello world和用户认证

    xiaoxiao2021-03-25  294

    Shiro 入门与身份认证

    本节介绍了 Shiro 的入门示例程序。

    "身份认证"是 Shiro 里很重要的概念。 "认证"就是通过输入用户名和密码,到内存中或者到数据库中去查询是否有这个用户名的信息(且密码也匹配)。

    用户信息存放在“内存”中

    用户信息存放在"内存"中,意即将用户的用户名和密码信息存放在一个名为 shiro.ini 的文件中。 更多的情况是,我们把用户的用户名和密码信息存放在数据库中,这也是我们以前做的项目的绝大多数情况下的做法。

    创建 maven 项目。 1、引入jar依赖pom.xml:

    <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency>

    2、编写 shiro 核心配置文件 src目录下shiro.ini

    [users] demo=1234

    3、编写 HelloWorld 代码

    这里要特别注意:SecurityManager 所在的包名应该是org.apache.shiro.mgt。

    import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import sun.org.mozilla.javascript.internal.SecurityUtilities; public class HelloWorld { public static void main(String[] args) { // 读取配置文件,初始化 SecurityManager 工厂 // 注意:这里 SecurityManager 所在的包名 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); // 获取 SecurityManager 的实例 SecurityManager securityManager = factory.getInstance(); // 把 securityManager 的实例绑定到 SecurityUtils 上 SecurityUtils.setSecurityManager(securityManager); // 得到当前执行的用户 Subject currentUser = SecurityUtils.getSubject(); // 自己创建一个令牌,输入用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("demo","1234"); try { // 身份认证(该方法会抛出异常) currentUser.login(token); System.out.println("身份认证成功!"); } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("账号不存在!"); } catch (AuthenticationException e) { e.printStackTrace(); System.out.println("密码错误!"); } // 退出 currentUser.logout(); } }

    4、引入 slf4j 的 log4j 实现配置文件:log4j.properties

    log4j.rootLogger =info,console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d %p %c.%M()-%m%n

    Subject 认证主体包含两个信息: Principals:身份,可以是用户名,邮件,手机号码等等,用来标识一个登录主体身份;(我们可以理解成用户名) Credentials:凭证,常见有密码,数字证书等等;(我们可以理解成密码)

    用户信息存放在数据库中

    下面我们介绍使用 JdbcRealm。那么什么是 Realm 呢? Realm 可以理解为主体的数据源(数据来源,里面存放的都是正确的用户名和密码)。 Realm 的意思是域,Shiro 从 Realm 中获取验证数据。

    只须要对上面的代码稍稍作修改就可以实现将用户信息存放在数据库中,通过数据库中的用户信息进行登录匹配。既然使用的是 JdbcRealm,就须要使用到 jdbc 的相关技术。 首先我们引入依赖pom.xml:

    <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <!-- c3p0连接池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency>

    再向数据库里写入数据:

    这里的表名和字段名都是固定的(数据库名称无所谓),这一点我们通过看 JdbcRealm 的源代码就可以知道。不过显然这样的方式显然是不灵活的。

    DROP TABLE IF EXISTS users; CREATE TABLE users ( id int(11) NOT NULL AUTO_INCREMENT, userName varchar(20) DEFAULT NULL, password varchar(20) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; insert into users(userName,password) values ('demo','1234');

    配置文件src目录下 jdbc_realm.ini:

    [main] jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm dataSource=com.mchange.v2.c3p0.ComboPooledDataSource dataSource.jdbcUrl=jdbc:mysql://localhost:3306/shiro_test dataSource.password=root dataSource.user=root dataSource.driverClass=com.mysql.jdbc.Driver jdbcRealm.dataSource=$dataSource securityManager.realm=$jdbcRealm

    配置文件解释:

    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm 表示实例化右边字符串表示的类,赋给左边字符串表示的变量。 dataSource.jdbcUrl=jdbc:MySQL://localhost:3306/shiro_test表示对 dataSource 这个变量设置属性值 jdbcUrl ,这个属性值是一个字符串。 jdbcRealm.dataSource= dataSourcejdbcRealmdataSourcedataSource使

    测试代码

    @Test public void mian1111() { // 读取配置文件,初始化 SecurityManager 工厂 // 注意:这里 SecurityManager 所在的包名 Factory<SecurityManager> factory = new IniSecurityManagerFactory( "classpath:jdbc_realm.ini"); // 获取 SecurityManager 的实例 SecurityManager securityManager = factory.getInstance(); // 把 securityManager 的实例绑定到 SecurityUtils 上 SecurityUtils.setSecurityManager(securityManager); // 得到当前执行的用户 Subject currentUser = SecurityUtils.getSubject(); // 自己创建一个令牌,输入用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("demo", "1234"); try { // 身份认证(该方法会抛出异常) currentUser.login(token); System.out.println("身份认证成功!"); } catch (AuthenticationException e) { e.printStackTrace(); System.out.println("身份认证失败!"); } // 退出 currentUser.logout(); }

    补充:在 currentUser.login(token); 这一行捕获的异常,这里只是简单地捕获了 AuthenticationException 这个异常,我们还可以具体地捕获用户名不存在异常和密码不存在异常。

    总结: 使用 Shiro 进行身份认证的流程是:将用户的用户名和密码信息存放在一个 UsernamePasswordToken 对象中,通过 Subject 的 login() 方法把 UsernamePasswordToken 对象传进去。

    此时 Shiro 框架会去 shiro.ini 文件中找指定的安全数据源 Realm。默认是 IniRealm ,如果我们配置了 JdbcRealm ,就使用 JdbcRealm。

    用户名是否存在,用户名存在的前提下密码是否也匹配,这个操作是由 Shiro 帮助我们完成的。

    转载请注明原文地址: https://ju.6miu.com/read-20.html

    最新回复(0)