SpringBoot 集成 Shiro,并使用多个 Realm
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
Token token = (Token) authenticationToken;
//判断是否有 Realm 装配
this.assertRealmsConfigured();
Collection<Realm> realms = getRealms();
//如果不唯一,分类进行
Collection<Realm> waitChooseRealms = new ArrayList<>();
for (Realm realm : realms) {
//遍历所有 Realm
//通过获取 Realm 的名字,比较 token 的信息,将想要执行的 Realm 放到新的 Realms 组合里面
if(realm.getName().contains(token.getLoginType())){
waitChooseRealms.add(realm);
}
}
//与源码一样,如果只有一个,就执行一个
if (realms.size() == 1){
return doSingleRealmAuthentication((Realm)waitChooseRealms.iterator().next(), token);
}
//与源码一样,如果有多个,就将整个 Realms 数组放进去
return doMultiRealmAuthentication(waitChooseRealms,token);
}
}
我自定义的 ModularRealmAuthentic 是根据 Realm 的名字来进行区分的,所以,Realm 的名字最后不要出现相同的关键字符串,比如下面我要创一个 user、manager 和 merchant 的 Realm,那么就不可以出现 usermerchant 这样的 Realm。否则,即会进行 userRealm,也会进行 merchantRealm。
UserRealm
这是原有的
/**
@Author: Ember
@Date: 2021/4/26 17:36
@Description:
*/
public class MyDiyModularRealmAuthenticator extends ModularRealmAuthenticator {
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
Token token = (Token) authenticationToken;
//判断是否有 Realm 装配
this.assertRealmsConfigured();
Collection<Realm> realms = getRealms();
//如果不唯一,分类进行
Collection<Realm> waitChooseRealms = new ArrayList<>();
for (Realm realm : realms) {
if(realm.getName().contains(token.getLoginType())){
waitChooseRealms.add(realm);
}
}
if (realms.size() == 1){
return doSingleRealmAuthentication((Realm)waitChooseRealms.iterator().next(), token);
}
return doMultiRealmAuthentication(waitChooseRealms,token);
}
}
ManagerRealm 和 MerchantRealm
这两个 Realm 只做测试使用,所以就不详细做认证和授权操作了
/**
@Author: Ember
@Date: 2021/4/26 17:47
@Description:
*/
public class ManagerRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("=======进入了 ManagerRealm=========");
return null;
}
}
/**
@Author: Ember
@Date: 2021/4/26 17:49
@Description:
*/
public class MerchantRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("=========进入了 MerchantRealm===========");
return null;
}
}
因为自定义了多个 Realm,还有 ModularRealmAuthentic,所以这些我们都要装配上
/**
@Author: Ember
@Date: 2021/4/2 18:05
@Description: ShiroConfig
*/
@Configuration
public class MyShiroConfig{
/**
ShiroFactoryBean 装配安全管理
@param defaultSecurityManager
@return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager defaultSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//这里要让 ThredContext 对 defaultSecurityManager 绑定,否则会报错
ThreadContext.bind(defaultSecurityManager);
shiroFilterFactoryBean.setSecurityManager(defaultSecurityManager);
return shiroFilterFactoryBean;
}
/**
安全管理装配 Realm
@param realm
@return
*/
@Bean
public DefaultSecurityManager defaultSecurityManager(
@Qualifier("myRealm") MyUserRealm realm,
@Qualifier("MerchantRealm") MerchantRealm merchantRealm,
@Qualifier("ManagerRealm") ManagerRealm managerRealm,
@Qualifier("authent
icator") MyDiyModularRealmAuthenticator authenticator){
//注意这里要是 DefaultWebSecurityManager,否则报错
DefaultSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setAuthenticator(authenticator);
//装配上 Realm
Collection<Realm> realms = new ArrayList();
realms.add(realm);
realms.add(merchantRealm);
realms.add(managerRealm);
//securityManager.setRealm(realm);
// securityManager.setRealm(merchantRealm);
securityManager.setRealms(realms);
return securityManager;
}
/**
自定义的 ModularRealmAuthenticator
@return
*/
@Bean(name = "authenticator")
public MyDiyModularRealmAuthenticator modularRealmAuthenticator(){
MyDiyModularRealmAuthenticator myDiyModularRealmAuthenticator = new MyDiyModularRealmAuthenticator();
myDiyModularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return myDiyModularRealmAuthenticator;
}
/**
自定义 Realm
@return
*/
@Bean(name = "MerchantRealm")
public MerchantRealm merchantRealm(){
MerchantRealm realm = new MerchantRealm();
//自定义校验匹配器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//设置加密算法为 md5
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//设置加密算法的散列次数
hashedCredentialsMatcher.setHashIterations(1024);
//将自定义匹配添加进 Realm 中
realm.setCredentialsMatcher(hashedCredentialsMatcher);
//todo 设置缓存
return realm;
}
@Bean(name = "ManagerRealm")
public ManagerRealm managerRealm(){
ManagerRealm realm = new ManagerRealm();
//自定义校验匹配器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//设置加密算法为 md5
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//设置加密算法的散列次数
hashedCredentialsMatcher.setHashIterations(1024);
//将自定义匹配添加进 Realm 中
realm.setCredentialsMatcher(hashedCredentialsMatcher);
//todo 设置缓存
return realm;
}
@Bean(name = "myRealm")
public MyUserRealm realm(){
MyUserRealm realm = new MyUserRealm();
//自定义校验匹配器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//设置加密算法为 md5
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//设置加密算法的散列次数
hashedCredentialsMatcher.setHashIterations(1024);
//将自定义匹配添加进 Realm 中
realm.setCredentialsMatcher(hashedCredentialsMatcher);
//todo 设置缓存
return realm;
}
}
如果没有让 ThreadContext 绑定 securityManager,会报错,如下图
评论