我们做shiro框架经常会遇到这种情况,用户数量很多,又不在同一个表里,比如管理员一个表,用户一个表,商家一个表。这时我们就需要用到多realm来配置让他们用不同得realm来进行权限认证
跟登录认证一样,首先我们来说思路,因为权限认证的话肯定已经登录过了,那么我们就可以通过principals.getPrimaryPrincipal()获取当前登录的用户信息,然后对其进行判断看看他是哪个用户Bean的实体类以此来判断当前用哪个realm来认证
首先我们要写一个用于选择用哪个realm来认证的MyAuthorizer类继承ModularRealmAuthorizer类
/*
MyAuthorizer类继承后重写其中的isPermitted(PrincipalCollection principals, String permission),
isPermitted(PrincipalCollection principals, Permission permission),
hasRole(PrincipalCollection principals, String roleIdentifier)
三个方法,其中isPermitted方法是用来验证权限,hasRole方法是用来验证角色的
*/
public class MyAuthorizer extends ModularRealmAuthorizer {
/**
* Returns <code>true</code> if any of the configured realms'
* {@link #isPermitted(PrincipalCollection, String)} returns <code>true</code>,
* <code>false</code> otherwise.
*
* @param principals
* @param permission
*/
@Override
public boolean isPermitted(PrincipalCollection principals, String permission) {
return super.isPermitted(principals, permission);
}
/**
* Returns <code>true</code> if any of the configured realms'
* {@link #isPermitted(PrincipalCollection, Permission)} call returns <code>true</code>,
* <code>false</code> otherwise.
*
* @param principals
* @param permission
*/
@Override
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
return super.isPermitted(principals, permission);
}
/**
* Returns <code>true</code> if any of the configured realms'
* {@link #hasRole(PrincipalCollection, String)} call returns <code>true</code>,
* <code>false</code> otherwise.
*
* @param principals
* @param roleIdentifier
*/
@Override
public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
return super.hasRole(principals, roleIdentifier);
}
}
三个方法里得内容基本差不多,所以这里只提供hasRole方法的写法
public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
//判断realm是否存在
assertRealmsConfigured();
//获取当前登录对象实例
Object primaryPrincipal = principals.getPrimaryPrincipal();
//getRealms()获取当前所有的Realm,遍历所有的realm
Iterator iterator=getRealms().iterator();
while (iterator.hasNext()){
Realm realm=(Realm) iterator.next();
//判断是否是一个realm
if (!(realm instanceof Authorizer)) continue;
//判断当前登录对象实例是否为管理员实例
if (primaryPrincipal instanceof Administrators) {
if (realm instanceof AdminRealm)
return ((AdminRealm) realm).hasRole(principals, roleIdentifier);
}
//判断当前登录对象实例是否为用户实例
if (primaryPrincipal instanceof User) {
if (realm instanceof UserRealm)
return ((UserRealm) realm).hasRole(principals, roleIdentifier);
}
//判断当前登录对象实例是否为商户实例
if (primaryPrincipal instanceof Merchants) {
if (realm instanceof MerchantsRealm)
return ((MerchantsRealm) realm).hasRole(principals, roleIdentifier);
}
}
return false;
}
至于isPermitted方法就是把其中的return ((UserRealm) realm).hasRole(principals, roleIdentifier);换为return ((UserRealm) realm).isPermitted(principals, permission);
然后还是一样将这个东西放到shiro配置文件里,告诉shiro用这个东西来决定用哪个realm来验证权限
@Bean
public org.apache.shiro.mgt.SecurityManager securityManager(){
DefaultWebSecurityManager defaultSecurityManager=new DefaultWebSecurityManager();
defaultSecurityManager.setAuthenticator(customizedModularRealmAuthenticator());
//将三个realm放置shiro装配到shiro框架中
List<Realm> realms=new ArrayList<>();
realms.add(userRealm());
realms.add(adminRealm());
realms.add(merchantsRealm());
defaultSecurityManager.setRealms(realms);
//多realm授权配置
CustomerAuthrizer customerAuthrizer=new CustomerAuthrizer();
customerAuthrizer.setRealms(realms);
defaultSecurityManager.setAuthorizer(customerAuthrizer);
return defaultSecurityManager;
}
@Bean
public AdminRealm adminRealm(){
AdminRealm adminRealm=new AdminRealm();
//将密码加密与验证装配到realm中
adminRealm.setCredentialsMatcher(credentialsMatcher());
return adminRealm;
}
@Bean
public UserRealm userRealm(){
UserRealm userRealm=new UserRealm ();
//将密码加密与验证装配到realm中
userRealm.setCredentialsMatcher(credentialsMatcher());
return userRealm;
}
@Bean
public MerchantsRealm merchantsRealm(){
MerchantsRealm merchantsRealm=new MerchantsRealm();
//将密码加密与验证装配到realm中
merchantsRealm.setCredentialsMatcher(credentialsMatcher());
return merchantsRealm;
}
至此多realm权限认证配置完成,realm内部以及配置文件相关在以往的文章中有详细说明
有关realm登录认证请查看:shiro框架多realm登录认证配置