原创

springboot整合shiro配置多realm

封面

首先自定义一个DefaultUsernamepasswordToken.java,继承Shiro自带的UsernamePasswordToken,在DefaultUsernamepasswordToken中新加一个属性 private String loginType; 而后生成getter setter;

首先拓展shiro 中的UsernamePasswordToken:

        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
/** * 功能描述 TODO * 拓展shiro 中的UsernamePasswordToken * @author luoyuanxiang * {@link UsernamePasswordUsertypeToken} * @date 2018/12/25 10:10 */ public class UsernamePasswordUsertypeToken extends UsernamePasswordToken { private static final long serialVersionUID = 1L; /** * 登陆状态 app用户/管理员用户 */ private String loginType; public String getLoginType() { return loginType; } public void setLoginType(String loginType) { this.loginType = loginType; } public UsernamePasswordUsertypeToken(String loginName, String password,boolean rememberMe, String loginType) { super(loginName, password,rememberMe); this.loginType = loginType; } }

然后自定义一个DefautModularRealm.java,继承 ModularRealmAuthenticator,重写doMultiRealmAuthentication、doSingleRealmAuthentication、doAuthenticate三个方法,还需要定义一个变量, 用来接收传进来的多个Realm。

        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
/** * 功能描述 TODO * 自定义当使用多realm时管理器 * @author luoyuanxiang * {@link DefautModularRealm} * @date 2018/12/25 10:14 */ public class DefautModularRealm extends ModularRealmAuthenticator{ private Map<String, Object> definedRealms; /** * 多个realm实现 */ @Override protected AuthenticationInfo doMultiRealmAuthentication( Collection<Realm> realms, AuthenticationToken token) { return super.doMultiRealmAuthentication(realms, token); } /** * 调用单个realm执行操作 */ @Override protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) { // 如果该realms不支持(不能验证)当前token if (!realm.supports(token)) { throw new MyException("token错误!"); } AuthenticationInfo info = null; try { info = realm.getAuthenticationInfo(token); if (info == null) { throw new MyException("token不存在!"); } } catch (Exception e) { throw new MyException("系统错误!请联系管理员!"); } return info; } @Override protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) { //先判断Realm是否为空 assertRealmsConfigured(); //强转为自定义的Token UsernamePasswordUsertypeToken token = (UsernamePasswordUsertypeToken) authenticationToken; Realm realm = null; if (token.getLoginType().equals(Constant.UserType.SYS_ADMIN.getUserType())) { realm = (Realm) this.definedRealms.get("userRealm"); } if (token.getLoginType().equals(Constant.UserType.APP_ADMIN.getUserType())) { realm = (Realm) this.definedRealms.get("loginRealm"); } if (realm == null) { return null; } return this.doSingleRealmAuthentication(realm, authenticationToken); } public Map<String, Object> getDefinedRealms() { return definedRealms; } public void setDefinedRealms(Map<String, Object> definedRealms) { this.definedRealms = definedRealms; } }

这里需要注意是 其实 流程是:在给DefaultUsernamepasswordToken赋值时,将loginType设置成相应的参数,然后在doAuthenticate时判断,单个调用对应的Realm。 然后是配置shirconfig类:

        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
/** * 功能描述 TODO * * @author luoyuanxiang * {@link ShiroConfig} * @date 2018/12/17 13:43 */ @Slf4j @Configuration public class ShiroConfig { @Bean(name="shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager manager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(manager); //配置登录的url和登录成功的url bean.setLoginUrl("/login"); bean.setSuccessUrl("/index"); //配置访问权限 LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); //表示可以匿名访问 filterChainDefinitionMap.put("/sys/login","anon"); filterChainDefinitionMap.put("/captcha.jpg","anon"); filterChainDefinitionMap.put("/assets/**","anon"); filterChainDefinitionMap.put("/logout","anon"); filterChainDefinitionMap.put("/wechat/**","anon"); //表示需要认证才可以访问 filterChainDefinitionMap.put("/**", "authc"); bean.setFilterChainDefinitionMap(filterChainDefinitionMap); return bean; } @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } /** * 配置核心安全事务管理器 * @return SecurityManager */ @Bean(name="securityManager") public SecurityManager securityManager() { log.info("--------------shiro已经加载----------------"); DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //设置realm. securityManager.setAuthenticator(userModularRealmAuthenticator()); List<Realm> realms = new ArrayList<>(2); //添加多个Realm realms.add(loginRealm()); realms.add(userRealm()); securityManager.setRealms(realms); // 自定义缓存实现 使用redis securityManager.setCacheManager(redisCacheManager()); // 自定义session管理 使用redis securityManager.setSessionManager(sessionManager()); //注入Cookie(记住我)管理器(remenberMeManager) securityManager.setRememberMeManager(rememberMeManager()); return securityManager; } /** * cookie对象; * * @return SimpleCookie */ private SimpleCookie rememberMeCookie() { // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); // 记住我cookie生效时间30天 ,单位秒。 注释掉,默认永久不过期 2018-07-15 simpleCookie.setMaxAge(2592000); return simpleCookie; } /** * cookie管理对象;记住我功能 * * @return CookieRememberMeManager */ private CookieRememberMeManager rememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) cookieRememberMeManager.setCipherKey(Base64.decode("1QWLxg+NYmxraMoxAXu/Iw==")); return cookieRememberMeManager; } /** * 配置shiro redisManager * 使用的是shiro-redis开源插件 * * @return RedisManager */ @Bean public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); redisManager.setHost("192.168.2.106"); redisManager.setPort(6379); redisManager.setPassword(null); // 超时 秒 redisManager.setTimeout(6000); // 过期时间 秒 默认30天 redisManager.setExpire(2592000); return redisManager; } /** * cacheManager 缓存 redis实现 * 使用的是shiro-redis开源插件 * * @return RedisCacheManager */ @Bean @DependsOn("lifecycleBeanPostProcessor") public RedisCacheManager redisCacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); return redisCacheManager; } /** * Session Manager * 使用的是shiro-redis开源插件 */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultWebSessionManager sessionManager() { final DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); Cookie cookie = new SimpleCookie(java.util.UUID.randomUUID() + ShiroHttpSession.DEFAULT_SESSION_ID_NAME); sessionManager.setSessionIdCookie(cookie); sessionManager.setGlobalSessionTimeout(3600000); sessionManager.setDeleteInvalidSessions(true); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionDAO(redisSessionDAO()); return sessionManager; } /** * RedisSessionDAO shiro sessionDao层的实现 通过redis * 使用的是shiro-redis开源插件 */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); return redisSessionDAO; } /** * 配置自定义的权限登录器 pc登陆 * @return UserRealm */ @Bean @DependsOn("lifecycleBeanPostProcessor") public UserRealm userRealm() { return new UserRealm(); } /** * 配置自定义的权限登录器 app登陆 * @return LoginRealm */ @Bean @DependsOn("lifecycleBeanPostProcessor") public LoginRealm loginRealm() { return new LoginRealm(); } /** * 配置自定义当使用多realm时管理器 * */ @Bean public ModularRealmAuthenticator userModularRealmAuthenticator(){ DefautModularRealm modularRealmAuthenticator = new DefautModularRealm(); modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy()); Map<String, Object> definedRealms = new HashMap<>(2); definedRealms.put("loginRealm",loginRealm()); definedRealms.put("userRealm",userRealm()); modularRealmAuthenticator.setDefinedRealms(definedRealms); return modularRealmAuthenticator; } @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){ return new LifecycleBeanPostProcessor(); } @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager()); return advisor; } }

最后就是配置realm验证了:app登陆验证LoginRealm和系统登陆验证UserRealm 其中的内容就不一一赘述了和之前的配置完全一样 到此就可以实现多用户登陆验证了

本文于   2019/6/11 上午  发布在  宁静寺  分类下,当前已被围观  119  次

相关标签: 计算机 网络 学习 Web开发

永久地址: https://luoyuanxiangvip.com/article/1

版权声明: 自由转载-署名-非商业性使用   |   Creative Commons BY-NC 3.0 CN