上篇博客中简单介绍了一下权限管理的原理,其中包括最主要的两部分认证和授权。这篇博客中简单介绍一下shiro的认证和授权过程。
Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。
既然可以基于url实现权限的管理,为什么还要用shiro呢??
1.shiro将安全认证相关的功能抽取出来组成一个框架,使用shiro就可以非常快速的完成认证、授权等功能的开发,降低系统成本。最主要的就是方便了我们的开发。
2.shiro使用广泛,shiro可以运行在web应用,非web应用,集群分布式应用中越来越多的用户开始使用shiro。
认证流程:
实例:
1.创建一个java工程,并加入shiro-core的jar包以及它的依赖包。
2.自定义realm
Shiro有自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。
public class CustomRealm extends AuthorizingRealm {
@Override
public String getName() {
return "customRealm";
}
// 用于认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// token是用户输入的
// 第一步从token中取出身份信息
String userCode = (String) token.getPrincipal();
// 第二步:根据用户输入的userCode从数据库中查询
// 模拟从数据库查询到密码
String password = "111111";
// 如果查询到返回认证信息AuthenticationInfo
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
userCode, password, this.getName());
return simpleAuthenticationInfo;
}
}
3.配置shiro-realm.ini文件
[main]
#自定义realm
customRealm=cn.itcast.shiro.realm.CustomRealm
#将realm设置到securityManager,相当于spring中注入
securityManager.realms=$customRealm
4.创建认证代码
// 用户登录和退出
@Test
public void testCustomRealm() {
// 创建securityManager工厂,通过ini配置文件创建securityManager工厂
Factory factory = new IniSecurityManagerFactory(
"classpath:shiro-realm.ini");
// 通过工厂创建SecurityManager
SecurityManager securityManager = factory.getInstance();
// 将securityManager设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
// 创建一个Subject实例,该实例认证要使用上边创建的securityManager进行
Subject subject = SecurityUtils.getSubject();
// 创建token令牌,记录用户认证的身份和凭证即账号和密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
"111111");
try {
// 用户登陆
subject.login(token);
} catch (AuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 用户认证状态
Boolean isAuthenticated = subject.isAuthenticated();
System.out.println("用户认证状态:" + isAuthenticated);
// 用户退出
subject.logout();
isAuthenticated = subject.isAuthenticated();
System.out.println("用户认证状态:" + isAuthenticated);
}
5.认证流程
(1)创建token令牌,token中有用户提交的认证信息即账号和密码
(2)执行subject.login(token),最终由securityManager通过Authenticator进行认证
(3)Authenticator的实现ModularRealmAuthenticator调用realm从数据库中取用户真实的账号和密码
(4)CustomRealm先根据token中的账号去数据库中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。
6.测试
登录时用户认证成功,退出时用户认证失败。
授权流程
授权方式
shiro支持三种方式的授权:
1.编程式
Subject subject = SecurityUtils.getSubject();
if(subject.hasPermission(“admin”)) {
//有权限
} else {
//无权限
}
2.注解式
@RequiresPermissions("admin")
public void hello() {
//有权限
}
3.JSP/GSP标签
在web系统集成中使用后两种方式,我在这儿举个简单的例子就用第一种方式了。
实例
1.自定义realm
// 用于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
// 获取身份信息
//将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到Simpl)
String username = (String) principals.getPrimaryPrincipal();
// 根据身份信息从数据库中查询权限数据
// ....这里使用静态数据模拟
List permissions = new ArrayList();
permissions.add("user:create");
permissions.add("user:delete");
// 将权限信息封闭为AuthorizationInfo
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (String permission : permissions) {
simpleAuthorizationInfo.addStringPermission(permission);
}
return simpleAuthorizationInfo;
}
2.配置shiro-realm.ini文件与上面认证配置文件相同
3.创建授权代码
// 自定义realm进行资源授权测试
@Test
public void testAuthorizationCustomRealm() {
// 从ini文件中创建SecurityManager工厂
Factory factory = new IniSecurityManagerFactory(
"classpath:shiro-realm.ini");
// 创建SecurityManager
SecurityManager securityManager = factory.getInstance();
// 将securityManager设置到运行环境
SecurityUtils.setSecurityManager(securityManager);
// 创建主体对象
Subject subject = SecurityUtils.getSubject();
// 对主体对象进行认证
// 用户登陆
// 设置用户认证的身份(principals)和凭证(credentials)
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
"111111");
try {
subject.login(token);
} catch (AuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 用户认证状态
Boolean isAuthenticated = subject.isAuthenticated();
System.out.println("用户认证状态:" + isAuthenticated);
// 授权检测,失败则抛出异常
// subject.checkRole("role22");
// 基于资源授权
System.out.println("是否拥有某一个权限:" + subject.isPermitted("user:delete"));
System.out.println("是否拥有多个权限:"
+ subject.isPermittedAll("user:update", "user:delete"));
// 检查权限
subject.checkPermission("user:delete");
}
4.授权流程
(1)执行subject.isPermitted("user:delete")
(2)securityManager通过ModularRealmAuthorizer进行授权
(3)ModularRealmAuthorizer调用realm获取权限信息
(4)ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配
5.测试
表明该用户拥有delete权限但是不拥有update权限。
现在只是跟着燕青老师做了几个简单的demo而已,接下来要好好研究一下与ITOO项目的整合,还需要继续努力!再次再推荐一下,燕青老师讲的这套视频真心不错。