Shiro(五)Realm配置

259 阅读2分钟

Reaml介绍

Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。如我们之前的 ini 配置方式将使用org.apache.shiro.realm.text.IniRealm 或者是通过集成实现的AuthorizingRealm

image.png

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;
    }