三、Shiro基础
3.1 项目搭建
3.1.1 建立Maven项目
建立Java项目即可。
3.1.2 引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.newcapec</groupId>
<artifactId>shiro01-base</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.1</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- 德鲁伊数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 日志
slf4j:日志记录系统的简单外观,日志空实现(日志规范、日志接口)
真正记录日志的框架(日志实现框架):log4j、logback等
slf4j是一个日志标准,同时日志框架都会实现这个标准,因此使用slf4j可以极大的降低维护成本。
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3.2 身份认证
身份认证:用户身份识别,俗称为“用户登录”。
3.2.1 认证流程
1、创建SecurityManager。
2、主体提交认证。
3、SecurityManager认证。
4、SecurityManager是用Authenticator来认证。
5、authenticator认证是通过Realm获取认证数据做最终的认证。
3.2.2 测试用例
public class HelloWorldTest {
/**
* 演示Shiro实现用户登录:身份认证
*/
@Test
public void run(){
// 1.创建Shiro环境SecurityManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// 2.创建Realm对象: SimpleAccountRealm管理账户的Realm
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
// 设置基础用户信息(相当于数据库中存储的用户信息)
simpleAccountRealm.addAccount("admin", "123");
simpleAccountRealm.addAccount("tom", "111");
// 3.设置指定Realm
securityManager.setRealm(simpleAccountRealm);
// 4.构建环境:把创建的SecurityManager和Realm告知给Shiro
SecurityUtils.setSecurityManager(securityManager);
// 5.获取当前操作的主体Subject
Subject subject = SecurityUtils.getSubject();
// 6.创建一个存储用户名与密码的令牌,用户输入用户名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "123");
// 7.登录
subject.login(usernamePasswordToken);
System.out.println("身份认证结果:" + subject.isAuthenticated());
}
}
3.2.3 认证异常
用户名提供错误时抛出的异常:
org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.SimpleAccountRealm@5594a1b5] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - jerry, rememberMe=false].
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:184)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at com.newcapec.HelloWorldTest.run(HelloWorldTest.java:39)
密码提供错误时抛出的异常:
org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false] did not match the expected credentials.
at org.apache.shiro.realm.AuthenticatingRealm.assertCredentialsMatch(AuthenticatingRealm.java:603)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:581)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at com.newcapec.HelloWorldTest.run(HelloWorldTest.java:39)
3.3 权限鉴定
3.3.1 鉴权流程
1、创建SecurityManager。
2、主体授权。
3、SecurityManager执行授权。
4、Authorizer执行授权。
5、Realm获取角色权限数据。
3.3.2 测试用例
public class RoleTest {
@Test
public void run() {
// 1.创建Shiro环境SecurityManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// 2.创建Realm对象: SimpleAccountRealm管理账户的Realm
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
// 设置基础用户信息,以及角色
simpleAccountRealm.addAccount("admin", "123", "root", "user");
simpleAccountRealm.addAccount("tom", "111", "user");
// 3.设置指定Realm
securityManager.setRealm(simpleAccountRealm);
// 4.构建环境
SecurityUtils.setSecurityManager(securityManager);
// 5.获取当前操作的主体Subject
Subject subject = SecurityUtils.getSubject();
// 6.创建一个存储用户名与密码的令牌,用户输入用户名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "123");
// 7.登录
subject.login(usernamePasswordToken);
// 判断当前用户是否身份认证成功
System.out.println("身份认证结果:" + subject.isAuthenticated());
// 判断当前用户是否用拥有指定的角色
// 方式一、subject.hasRole(角色编码); 返回值boolean类型。判断是否拥有角色。
System.out.println("是否拥有root角色:" + subject.hasRole("root"));
System.out.println("是否拥有user角色:" + subject.hasRole("user"));
// 方式二、subject.hasRoles(角色编码集合); 返回值boolean类型数组。判断是否拥有角色。其中返回数据为针对每个角色的鉴定结果。
boolean[] roles = subject.hasRoles(Arrays.asList("root", "user"));
System.out.println("是否拥有root、user角色:" + Arrays.toString(roles));
// 方式三、subject.hasAllRoles(角色编码集合); 返回值boolean类型。判断段是否拥有所有的角色。
System.out.println("是否同时拥有root、user角色:" + subject.hasAllRoles(Arrays.asList("root", "user")));
// 方式四、subject.checkRole(角色编码); 无返回值。如果拥有指定角色程序不抛出异常,否则抛出异常。
// subject.checkRole("root");
// subject.checkRole("user");
// 其他...
// 8.登出
subject.logout();
System.out.println("身份认证结果:" + subject.isAuthenticated());
System.out.println("是否拥有root角色:" + subject.hasRole("root"));
System.out.println("是否拥有user角色:" + subject.hasRole("user"));
}
}