shiro配置多realm,会执行多次授权操作即执行各个realm的doGetAuthorizationInfo方法
查看原因
- 调用授权
Subject subject = SecurityUtils.getSubject();
subject.isPermitted("abc");
- 进入isPermitted方法
会进入Subject接口下的一个实现类DelegatingSubject其中方法:
public boolean isPermitted(String permission) {
return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
}
- 进入SecurityManager的isPermitted方法
说明:Authorizer(授权器/者)下有很多实现类,如下图:
- 进入ModilarRealmAuthorizer找到如下方法:
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
//只要是Authorizer下的realm都会去认证,也就意味着多个realm都会认证。不知道能不能这样理解。如有错误,麻烦指正。
if (((Authorizer) realm).isPermitted(principals, permission)) {
return true;
}
}
return false;
}
解决方案
使用自定义的RealmAuthorizer
package com.finn.springboot002.common.config.shiro.config;
import com.finn.springboot002.common.config.shiro.realms.JwtRealm;
import org.apache.shiro.authz.Authorizer;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 自定义授权器。
* 解决授权使用ShiroRealm的doGetAuthorizationInfo问题
*/
public class CustomerAuthrizer extends ModularRealmAuthorizer {
@Override
public boolean isPermitted(PrincipalCollection principals, String permission) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
//做一个类型判断
if (realm instanceof JwtRealm) {
return ((JwtRealm) realm).isPermitted(principals, permission);
}
}
return false;
}
}
然后需要在你的shiroConfig配置该bean
@Bean
public ModularRealmAuthorizer authorizer(){
ModularRealmAuthorizer authorizer = new CustomerAuthrizer();
return authorizer;
}
继续在shiroConfig配置文件中,securityManager配置
@Bean(value = "securityManager")
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//1.使用自定义认证器
securityManager.setAuthenticator(authenticator());
//2.使用自定义授权器
securityManager.setAuthorizer(authorizer());
//更多配置
return securityManager;
}
这样会解决isPermitted的授权问题。其他的如:
checkPermission
hasRole
等策略,需要自行配置。
总结
我感觉不靠谱!!!不知道有没有其他解决方案。而且原因找的不是很令人信服。有大佬了解的话。感谢指导!!!