Reaml介绍
Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。如我们之前的 ini 配置方式将使用org.apache.shiro.realm.text.IniRealm 或者是通过集成实现的AuthorizingRealm
在Realm接口中并没有对Reaml做什么具体的逻辑
//返回一个唯一的Realm名字
String getName();
//判断此Realm是否支持此认证Token
boolean supports(AuthenticationToken token);
//根据Token获取认证信息
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
Realm 配置
单Realm
public class MyRealm implements Realm {
@Override
public String getName() {
return "myrealm";
}
@Override
public boolean supports(AuthenticationToken token) {
//仅支持AuthenticationToken及其子类类型的Token
return token instanceof AuthenticationToken;
}
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {}
//认证
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String)token.getPrincipal(); //得到用户名
String password = new String((char[])token.getCredentials()); //得到密码
if(!"zhang".equals(username)) {
throw new UnknownAccountException(); //如果用户名错误
}
if(!"123".equals(password)) {
throw new IncorrectCredentialsException(); //如果密码错误
}
//如果身份认证验证成功,返回一个AuthenticationInfo实现;
return new SimpleAuthenticationInfo(username, password, getName());
}
}
INI配置文件
#声明一个realm
myRealm=com.xxx.realm.MyRealm
#指定securityManager的realms实现
securityManager.realms=$myRealm
配置类
@Configuration
public class ShiroConfig {
//Realm 代表资源
@Bean
public Realm getRealm(){
return new MyRealm();
}
//SecurityManager 用作流程控制
@Bean
public DefaultWebSecurityManager mySecurityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(getRealm());
return securityManager;
}
//ShirFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultSecurityManager mySecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(mySecurityManager);
return shiroFilterFactoryBean;
}
}
多Realm
多Realm与单Realm配置的主要不同就是在配置文件或者配置上的设置 ini配置文件
#声明一个realm
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2
#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2
配置类 当配置了多个Realm时,我们通常使用的认证器是shiro自带的org.apache.shiro.authc.pam.ModularRealmAuthenticator,其中决定使用的Realm的是doAuthenticate()方法
public class UserModularRealmAuthenticator extends ModularRealmAuthenticator {
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
assertRealmsConfigured();
//依据Realm中配置的支持Token来进行过滤
List<Realm> realms = this.getRealms()
.stream()
.filter(realm -> realm.supports(authenticationToken))
.collect(Collectors.toList());
if (realms.size() == 1) {
return doSingleRealmAuthentication(realms.get(0), authenticationToken);
} else {
return doMultiRealmAuthentication(realms, authenticationToken);
}
}
}
在ShiroConfig中设置安全管理器添加多个自定义realm
/**
* 安全管理器
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm.
securityManager.setAuthenticator(modularRealmAuthenticator());
List<Realm> realms = new ArrayList<>();
//添加多个Realm
realms.add(userRealm());
securityManager.setRealms(realms);
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManagers());
return securityManager;
}
/**
* 系统自带的Realm管理,主要针对多realm
* */
@Bean
public ModularRealmAuthenticator modularRealmAuthenticator(){
//自己重写的ModularRealmAuthenticator
UserModularRealmAuthenticator modularRealmAuthenticator = new UserModularRealmAuthenticator();
modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return modularRealmAuthenticator;
}
/**
* 创建自定义Realm
* @return
*/
@Bean
public UserRealm userRealm(){
UserRealm userRealm = new UserRealm();
userRealm.setCachingEnabled(true);
//启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
userRealm.setAuthenticationCachingEnabled(true);
//启用授权缓存,即缓存AuthorizationInfo信息,默认false
userRealm.setAuthorizationCachingEnabled(true);
//配置自定义密码比较器
userRealm.setCredentialsMatcher(credentialsMatcher());
return userRealm;
}