经过实践的Shiro配置,利用 sSOInterceptor 进行sso登录拦截
配置
@Configurationpublic class ShiroConfiguration extends BaseLogger { @Autowired(required = false) private SSOInterceptor sSOInterceptor; @Autowired(required = false) private CacheUtils cacheUtils; //将自己的验证方式加入容器 @Bean public UserShiroRealm myShiroRealm() { //自定义realm,授权+登录 UserShiroRealm myShiroRealm = new UserShiroRealm(); //自定义login token类型 myShiroRealm.setAuthenticationTokenClass(XXAuthenticationToken.class); return myShiroRealm; } //权限管理,配置主要是Realm的管理认证 @Bean public DefaultWebSecurityManager securityManager(UserShiroRealm userShiroRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userShiroRealm); //web session管理 DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); //企业级缓存sessionDao,获取和保存session,这里session将保存到cacheManager中 sessionManager.setSessionDAO(new EnterpriseCacheSessionDAO()); //安全管理器设置session控制器 securityManager.setSessionManager(sessionManager); //设置cacheManager,鉴权和session使用同一个cache,因为session为uuid,用户为用户名,不会冲突 securityManager.setCacheManager(new CacheManager() { @Override public Cache getCache(String name) throws CacheException { logger.info("get cache:{}", name); return new JimdbCache<>(cacheUtils, CacheConstants.shiroCacheKey("")); } }); return securityManager; } //Filter工厂,设置对应的过滤条件和跳转条件 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(org.apache.shiro.web.mgt.DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //url拦截权限定义 Map map = new HashMap<>(); //登出自己控制 //map.put("/logout","logout");自己控制登出 //对所有用户认证 map.put("/**", "authc"); //静态资源部校验 map.put("/static/**", "anon"); map.put("/checkAppOn.html", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); //登录地址,首页地址触发sso登录 shiroFilterFactoryBean.setLoginUrl("/"); //首页 shiroFilterFactoryBean.setSuccessUrl("/index"); //错误页面,认证不通过时跳转 shiroFilterFactoryBean.setUnauthorizedUrl("/error"); //自定义登录过滤器,校验登录,不能直接将filter放入Spring中,他会和ShiroFilter同级,造成混乱 shiroFilterFactoryBean.getFilters().put("authc", new XXAuthenticationFilter(sSOInterceptor)); return shiroFilterFactoryBean; } //加入注解的使用,不加入这个注解不生效 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.web.mgt.DefaultWebSecurityManager securityManager) { //注解支持,可支持类级、method级权限控制 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; }}
登录校验Filter
public class XXAuthenticationFilter extends AdviceFilter { private final static Logger LOGGER = LoggerFactory.getLogger(ErpAuthenticationFilter.class); private SSOInterceptor sSOInterceptor; public ErpAuthenticationFilter(SSOInterceptor sSOInterceptor) { this.sSOInterceptor = sSOInterceptor; } /** * 处理sso登录信息,且可登录,返回true * * @param srequest * @param sresponse * @return * @throws Exception */ protected boolean preHandle(ServletRequest srequest, ServletResponse sresponse) throws Exception { HttpServletRequest request = (HttpServletRequest) srequest; HttpServletResponse response = (HttpServletResponse) sresponse; try { //sSOInterceptor来控制跳转登录sso页 if (sSOInterceptor.preHandle(request, response, null)) { LoginContext loginContext = ActionContext.getLoginContext(); Subject subject = SecurityUtils.getSubject(); //没有登录时,自动登录系统 if(!subject.isAuthenticated()) { subject.login(new ErpAuthenticationToken(loginContext.getAccount(), loginContext)); } return true; } } catch (Exception e) { LOGGER.error("预处理登录信息失败", e); } //中止处理链条 return false; }}
登出
@RequestMapping(value = {"/logout", "/login"})public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException { LoginContext loginContext = ActionContext.getLoginContext(); //删除业务key cookieUtils.deleteCookie(response, Profiles.getCookieKey()); logger.info("用户:{} 退出", loginContext.getAccount()); //清缓存 cacheUtils.deleteObject(CacheConstants.manUserShiroCacheKey(loginContext.getAccount())); cacheUtils.deleteObject(CacheConstants.manUserMenuCacheKey(loginContext.getAccount())); //shiro登出 Subject subject = SecurityUtils.getSubject(); subject.logout(); //清除cookie removeCookie(response); ErpDotnetInterceptor.toErpLogin(request, response);}private void removeCookie(HttpServletResponse response) { Cookie cookie = new Cookie(Profiles.getCookieKey(),""); cookie.setMaxAge(0); response.addCookie(cookie);}