系列(三)讲述 SpringBoot整合Shiro 实现多Realm验证以及认证策略
目录
shiro是一个很好的登陆以及权限管理框架,但是默认是单realm单数据表,但是很多业务需求单realm是很难实现登陆以及权限管理的功能(比如业务中用户分布在不同的数据表),这个时候就需要使用多个Realm。
一、使用场景
存在这样一种场景,我们可能会把安全数据放到不同的数据库,比方说 mysql里有,oracle里也有,mysql里面的加密算法是MD5,oracle里面的加密算法是SHA1。这个时候我们进行用户认证时,就需要同时访问这两个数据库,就需要多个Realm。如果有多个Realm的话,还需要涉及到认证策略的问题。
二、多Realm验证
多重认证,主要的类是ModularRealmAuthenticator,他有两个需要配置的属性,一个是Collection(用于存储Realm),另一个是AuthenticationStrategy(用于存储验证的策略 )。
通过查看源码可以看到 ModularRealmAuthenticator.class 中的 doAuthenticate方法:
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
assertRealmsConfigured();
Collection<Realm> realms = getRealms();
if (realms.size() == 1) {
//一个realm
return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
} else {
//多个realm
return doMultiRealmAuthentication(realms, authenticationToken);
}
}
从上面doAuthenticate方法中可以看到:
如果有一个Realm 使用的是:
- doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
如果有多个Realm 使用的是:
- doMultiRealmAuthentication(realms, authenticationToken);
所以我们可以配置多个Realm 给到 ModularRealmAuthenticator 这个bean,将ModularRealmAuthenticator 单独配置为一个bean,将这个bean 配置给SecurityManager。
配置流程:
1.在原有代码的基础上,添加第二个Realm SecondRealm.java
SecondRealm.java 中的 加密算法 为 SHA1
package com.koncord.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.koncord.model.User;
import com.koncord.service.UserService;
/**
* 自定义 Realm
* @author Administrator
*
*/
public class SecondRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
/**
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("SecondRealm 执行授权逻辑");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加资源的授权字符串
//info.addStringPermission("user:add");
//导数据库查询当前登录用户的授权字符串
//获取当前登录用户
Subject subject=SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
User sbUser=userService.findUserByName(user.getName());
info.addStringPermission(sbUser.getPerms());
return info;
}
/**
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("SecondRealm 执行认证逻辑")