springboot-shiro-cas-redis集成session共享,权限共享

  • 1.准备jar依赖:
  • 2.重写realm,通过继承CasRealm ,MyShiroCasRealm.java
  • 3.shiro配置类编写:
  • 4.开发过程中遇到的坑
    • a.一般单点登录系统设计,会有一个CAS服务器,一个唯一的登录入口系统UC,还有多个子系统service1,service2...集成到UC,在集成工程中,MyShiroCasRealm 和ShiroCasConfig 代码一模一样,当时做的时候这里费了一定的时间。
    • b.自定义cookie的时候,要注意domain域名设置,如果是单点登录,各个系统要设置相同的父域名public.com,否则会出现每进入一个子系统都会生成一个session, 也就是session没有实现共享,在退出登录系统后,子系统中用户还有残留,切换用户后发现登录系统用户正确,但是进入子系统中,用户是上次登录的用户。
    • c.shiro集成了redis,利用myRedisCacheManager,将权限信息保存到redis中,实现了子系统中权限共享,比如按钮级别权限。
    • d.shiro集成了redis,利用dwsm.setSessionManager(redisSessionManager());将session信息保存到redis中,实现了子系统中session共享,进入每个子系统都是同一个session。 浏览器cookie的value就是该session的ID。
  • 5.end

1.准备jar依赖:

     <!--Shiro核心框架 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version><exclusions><exclusion><artifactId>commons-collections</artifactId><groupId>commons-collections</groupId></exclusion></exclusions></dependency><!-- Shiro使用Srping框架 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.0.1</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>2.1.3.RELEASE</version></dependency><!--shiro redis--><dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version><exclusions><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion></exclusions></dependency>

2.重写realm,通过继承CasRealm ,MyShiroCasRealm.java


import com.alibaba.fastjson.JSONObject;
import com.dongao.support.utils.Properties2YmlUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.security.RedisUtils;
import com.ruoyi.common.utils.security.ShiroCasUtils;
import com.ruoyi.framework.config.properties.CasProperties;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.project.system.menu.service.IMenuService;
import com.ruoyi.project.system.role.service.IRoleService;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.service.IUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;/*** 直接继承CasRealm类,然后CasRealm已经完成了数据的认证工作,我们直接调用父类的功能即可* @ClassName MyShiroCasRealm* @Author zhangcongming* @Version 1.0**/public class MyShiroCasRealm extends CasRealm {private static final Logger logger = LoggerFactory.getLogger(MyShiroCasRealm.class);private final String projectName = Properties2YmlUtils.getCommonYml("project.name");@Autowiredprivate IMenuService menuService;@Autowiredprivate IRoleService roleService;@Autowiredprivate IUserService userService;@Autowiredprivate CasProperties casProperties;@PostConstructpublic void initProperty(){// cas server地址setCasServerUrlPrefix(casProperties.getCasServerUrl());// 客户端回调地址,表示当你认证中心认证完成之后需要访问的service地址setCasService(casProperties.getCasServiceProject() + casProperties.getCasFilterUrlPattern());}/*** 权限认证,为当前登录的Subject授予角色和权限* 本例中该方法的调用时机为需授权资源被访问时* 并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache* 如果连续访问同一个URL(比如刷新),该方法不会被重复调用,Shiro有一个时间间隔(也就是cache时间,在ehcache-shiro.xml中配置),超过这个时间间隔再刷新页面,该方法会被执行*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {logger.info("##################Shiro--权限认证##################");User user = ShiroCasUtils.getSysUser();if(user==null){logger.info("ShiroCasUtils获取用户为空!");throw new AuthenticationException("登录用户为空!");}SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();// 角色列表Set<String> roles = new HashSet<String>();// 功能列表Set<String> menus = new HashSet<String>();// 管理员拥有所有权限if (user.isAdmin()){info.addRole("admin");info.addStringPermission("*:*:*");}else {roles = roleService.selectRoleKeys(user.getUserId());menus = menuService.selectPermsByUserId(user.getUserId());// 角色加入 AuthorizationInfo认证对象info.setRoles(roles);// 权限加入 AuthorizationInfo认证对象info.setStringPermissions(menus);}return info;}/*** 1、CAS认证 ,验证用户身份* 2、将用户基本信息设置到会话中(不用了,随时可以获取的)*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {logger.info("##################Shiro--登录认证##################");// 调用父类的认证,父类认证已经完成了AuthenticationInfo authenticationInfo = super.doGetAuthenticationInfo(token);if (authenticationInfo == null) {logger.warn("authenticationInfo为空,可能是退出了!");return null;}String account = (String) authenticationInfo.getPrincipals().getPrimaryPrincipal();logger.info("认证 account:"+account);User user;user = userService.selectUserByLoginName(account);if (user == null){throw new UnknownAccountException();}//重写了权限返回值List<Object> principals = CollectionUtils.asList(new Object[]{user, authenticationInfo.getPrincipals()});PrincipalCollection principalCollection = new SimplePrincipalCollection(principals, this.getName());SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principalCollection, authenticationInfo.getCredentials());return info;}/*** 清理缓存权限(这里是用redis保存的权限)*/public void clearCachedAuthorizationInfo(){this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());}
}

3.shiro配置类编写:

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.dongao.support.utils.Properties2YmlUtils;
import com.ruoyi.common.utils.security.MyRedisCacheManager;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.properties.CasProperties;
import com.ruoyi.framework.config.properties.RedisProperties;
import com.ruoyi.framework.config.properties.ShiroProperties;
import com.ruoyi.framework.shiro.realm.MyShiroCasRealm;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
import com.ruoyi.framework.shiro.web.filter.sync.LogoutCasFilter;
import com.ruoyi.framework.shiro.web.session.OnlineWebSessionManager;
import org.apache.shiro.cas.CasFilter;
import org.apache.shiro.cas.CasSubjectFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.filter.DelegatingFilterProxy;import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;/*** shiro+cas配置* @ClassName ShiroCasConfig* @Author zhangcongming* @Version 1.0* @Date 2019/6/20 0020 下午 2:04**/
@Configuration
public class ShiroCasConfig {private final String keyPrefix = Properties2YmlUtils.getCommonYml("spring.redis.sessionPrefix");/*** 配置的redis进行数据的缓存** @return*/@Bean(name = "myShiroCasRealm")public MyShiroCasRealm myShiroCasRealm() {MyShiroCasRealm realm = new MyShiroCasRealm();return realm;}/*** 设置单点退出的监听器,作用是将所有的过期的session将其从对应的映射关系中移除* 注册单点登出listener* SingleSignOutHttpSessionListener用于在Cas Client应用中的Session过期时将其从对应的映射关系中移除。** @return*/@Beanpublic ServletListenerRegistrationBean singleSignOutHttpSessionListener() {ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();bean.setListener(new SingleSignOutHttpSessionListener());//bean.setName(""); //默认为bean namebean.setEnabled(true);//设置优先级bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return bean;}/*** 注册单点登出filter* 设置单点退出的拦截器,在登录的时候,客户端会去服务端进行认证,此时认证成功之后,* 服务端会将地址和ST返回给客户端,而在此时该拦截器会将session跟ST绑定在一起,* 如果访问退出的时候,此时服务端也会将服务地址和ST返回,此时的监听器会将所有的session全部变为失效。* <p>* SingleSignOutFilter需要配置在所有Filter之前,当Cas Client通过Cas Server登录成功,* Cas Server会携带生成的Service Ticket回调Cas Client,* 此时SingleSignOutFilter会将Service Ticket与当前的Session绑定在一起。* 当Cas Server在进行logout后回调Cas Client应用时也会携带该Service Ticket,* 此时Cas Client配置的SingleSignOutFilter将会使对应的Session失效,进而达到登出的目的。** @return*/@Beanpublic FilterRegistrationBean singleSignOutFilter() {FilterRegistrationBean bean = new FilterRegistrationBean();bean.setName("singleSignOutFilter");bean.setFilter(new SingleSignOutFilter());//拦截所有的请求bean.addUrlPatterns("/*");bean.setEnabled(true);//设置优先级bean.setOrder(10);return bean;}/*** 退出过滤器*/public LogoutCasFilter logoutFilter(){LogoutCasFilter logoutFilter = new LogoutCasFilter();CasProperties casProperties = SpringUtils.getBean(CasProperties.class);String logoutUrl = casProperties.getCasServerUrl() + casProperties.getCasLogoutUrl()+ "?service="+casProperties.getCasServiceProject() + casProperties.getCasFilterUrlPattern();logoutFilter.setRedirectUrl(logoutUrl);return logoutFilter;}/*** 设置shiro的拦截器工厂类* 在设置拦截器的时候,需要先执行cas的拦截器,再执行shiro的拦截器** @param securityManager* @param casFilter* @return*/@Bean(name = "shiroFilter")public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager,CasFilter casFilter) {CasProperties casProperties = SpringUtils.getBean(CasProperties.class);String loginUrl = casProperties.getCasServerUrl() + "/login?service="+ casProperties.getCasServiceProject() + casProperties.getCasFilterUrlPattern();ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// 必须设置 SecurityManagershiroFilterFactoryBean.setSecurityManager(securityManager);// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面shiroFilterFactoryBean.setLoginUrl(loginUrl);// 登录成功后要跳转的连接shiroFilterFactoryBean.setSuccessUrl(casProperties.getLoginSuccessUrl());shiroFilterFactoryBean.setUnauthorizedUrl(casProperties.getUnauthorizedUrl());// 添加casFilter到shiroFilter中,注意,casFilter需要放到shiroFilter的前面Map<String, Filter> filters = new HashMap();filters.put("casFilter", casFilter);filters.put("logout",logoutFilter());shiroFilterFactoryBean.setFilters(filters);loadShiroFilterChain(shiroFilterFactoryBean);return shiroFilterFactoryBean;}/*** 设置配置的触发的地方:用于设置shiro的拦截器,和将每一个拦截器的生命周期交给spring去管理* 注册DelegatingFilterProxy(Shiro)注册DelegatingFilterProxy(shiro)  是一个代理类,用于管理拦截器的生命周期,* 所有的请求都会拦截 ,在创建的时候,filter的执行会优先于bean的执行,所以需要使用该类先来管理bean* <p>* 该步只是将当前的的生命周期交给了spring管理,具体的管理还是需要下面的LifecycleBeanPostProcessor的对象去进行操作** @return*/@Beanpublic FilterRegistrationBean delegatingFilterProxy() {FilterRegistrationBean filterRegistration = new FilterRegistrationBean();filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));//  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理//targetFilterLifecycle 指明作用于filter的所有生命周期filterRegistration.addInitParameter("targetFilterLifecycle", "true");filterRegistration.setEnabled(true);//拦截所有的请求filterRegistration.addUrlPatterns("/*");return filterRegistration;}/*** 上面设置了声明周期,下面进行设置生命周期的自动化* 设置方法的自动初始化和销毁,init和destory方法被自动调用。* 注意,如果使用了该类,则不需要手动初始化方法和销毁方法,否则出错** @return*/@Bean(name = "lifecycleBeanPostProcessor")public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}/*** 开启注解声明:* 开启shiro aop 的注解支持,使用代理的方式,所以需要开启代码的支持** @return*/@Beanpublic DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();//设置代理方式,true是cglib的代理方式,false是普通的jdk代理方式proxyCreator.setProxyTargetClass(true);return proxyCreator;}/*** 开启注解声明:** @param securityManager* @return*/@Beanpublic AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}/*** 配置shiro redisManager* 使用的是shiro-redis开源插件* @return*/@Bean(name="redisManager")public RedisManager redisManager() {RedisManager redisManager = new RedisManager();RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class);redisManager.setHost(redisProperties.getHostName());redisManager.setPort(redisProperties.getPort());// 配置缓存过期时间redisManager.setExpire(Integer.parseInt(String.valueOf(redisProperties.getExpire())));redisManager.setTimeout(redisProperties.getTimeout());redisManager.setPassword(redisProperties.getPassword());return redisManager;}/*** cacheManager 缓存 redis实现* 使用的是shiro-redis开源插件* @return*//*@Bean(name = "shiroRedisCacheManager")public RedisCacheManager redisCacheManager() {RedisCacheManager redisCacheManager = new RedisCacheManager();redisCacheManager.setRedisManager(redisManager());return redisCacheManager;}*//*** 使用自定义redis缓存管理器* 解决redis中key为非字符串乱码问题* @return*/@Bean(name = "myRedisCacheManager")public MyRedisCacheManager myRedisCacheManager() {MyRedisCacheManager myRedisCacheManager = new MyRedisCacheManager();return myRedisCacheManager;}/*** RedisSessionDAO shiro sessionDao层的实现 通过redis* 使用的是shiro-redis开源插件*/@Beanpublic RedisSessionDAO redisSessionDAO() {RedisSessionDAO redisSessionDAO = new RedisSessionDAO();redisSessionDAO.setRedisManager(redisManager());redisSessionDAO.setKeyPrefix(keyPrefix);return redisSessionDAO;}/*** shiro session的管理*/@Bean(name = "redisSessionManager")public DefaultWebSessionManager redisSessionManager() {CasProperties casProperties = SpringUtils.getBean(CasProperties.class);ShiroProperties shiroProperties = SpringUtils.getBean(ShiroProperties.class);DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();sessionManager.setSessionDAO(redisSessionDAO());//会话超时时间,单位:毫秒sessionManager.setGlobalSessionTimeout(casProperties.getSessionExpireTime() * 60 * 1000);//当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失sessionManager.setSessionIdCookie(shrioCookie());// 删除过期的sessionsessionManager.setDeleteInvalidSessions(true);// 去掉URL中的JSESSIONIDsessionManager.setSessionIdUrlRewritingEnabled(false);// 是否定时检查sessionsessionManager.setSessionValidationSchedulerEnabled(true);//定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话,单位为毫秒sessionManager.setSessionValidationInterval(shiroProperties.getSessionValidationInterval() * 60 * 1000);return sessionManager;}/*** cookie 属性设置*/public SimpleCookie shrioCookie(){ShiroProperties shiroProperties = SpringUtils.getBean(ShiroProperties.class);SimpleCookie cookie = new SimpleCookie("shiroCasCookie");//如果是单点登录,各个系统要设置相同的父域名public.com,否则会出现每进入一个子系统都会生成一个session,//也就是session没有实现共享,在退出后,子系统中用户还有残留!cookie.setDomain(“public.com”);//JSESSIONID的path为/用于多个系统共享JSESSIONIDcookie.setPath(shiroProperties.getPath());//浏览器中通过document.cookie可以获取cookie属性,设置了HttpOnly=true,在脚本中就不能得到cookie,可以避免cookie被盗用cookie.setHttpOnly(shiroProperties.isHttpOnly());/*maxAge=-1表示浏览器关闭时失效此Cookie*/cookie.setMaxAge(shiroProperties.getMaxAge() * 24 * 60 * 60);return cookie;}/*** @param myShiroCasRealm* @return*/@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(MyShiroCasRealm myShiroCasRealm) {DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();//用户授权/认证信息Cache, 采用EhCache 缓存CasProperties casProperties = SpringUtils.getBean(CasProperties.class);if (casProperties.isEhCacheSwitch()){dwsm.setCacheManager(myRedisCacheManager());}// 指定 SubjectFactorydwsm.setSubjectFactory(new CasSubjectFactory());dwsm.setSessionManager(redisSessionManager());dwsm.setRealm(myShiroCasRealm);return dwsm;}/*** thymeleaf模板引擎和shiro框架的整合*/@Beanpublic ShiroDialect shiroDialect() {return new ShiroDialect();}/*** CAS过滤器** @return*/@Bean(name = "casFilter")public CasFilter getCasFilter() {CasProperties casProperties = SpringUtils.getBean(CasProperties.class);String loginUrl = casProperties.getCasServerUrl() + "/login?service=" +casProperties.getCasServiceProject() + casProperties.getCasFilterUrlPattern();CasFilter casFilter = new CasFilter();//自动注入拦截器的名称casFilter.setName("casFilter");//是否自动的将当前的拦截器进行注入casFilter.setEnabled(true);// 登录失败后跳转的URL,也就是 Shiro 执行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer验证tiket// 我们选择认证失败后重新登录casFilter.setFailureUrl(loginUrl);return casFilter;}/*** 加载shiroFilter权限控制规则(从数据库读取然后配置),角色/权限信息由MyShiroCasRealm对象提供doGetAuthorizationInfo实现获取来的** @param shiroFilterFactoryBean*/private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();// authc:该过滤器下的页面必须登录后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter// anon: 可以理解为不拦截// user: 登录了就不拦截// roles["admin"] 用户拥有admin角色// perms["permission1"] 用户拥有permission1权限// filter顺序按照定义顺序匹配,匹配到就验证,验证完毕结束。// url匹配通配符支持:? * **,分别表示匹配1个,匹配0-n个(不含子路径),匹配下级所有路径//1.shiro集成cas后,首先添加该规则filterChainDefinitionMap.put("/", "casFilter");//2.不拦截的请求 对静态资源设置匿名访问filterChainDefinitionMap.put("/favicon.ico**", "anon");filterChainDefinitionMap.put("/css/**", "anon");filterChainDefinitionMap.put("/docs/**", "anon");filterChainDefinitionMap.put("/fonts/**", "anon");filterChainDefinitionMap.put("/img/**", "anon");filterChainDefinitionMap.put("/ajax/**", "anon");filterChainDefinitionMap.put("/js/**", "anon");filterChainDefinitionMap.put("/druid/**", "anon");filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");filterChainDefinitionMap.put("/error", "anon");// 退出 logout地址,shiro去清除session// 此处将logout页面设置为anon,而不是logout,因为logout被单点处理,而不需要再被shiro的logoutFilter进行拦截filterChainDefinitionMap.put("/logout", "logout");// 不需要拦截的访问filterChainDefinitionMap.put("/login", "anon");//不需要登录拦截的接口filterChainDefinitionMap.put("/system/api/**","anon");//3.拦截的请求(从本地数据库获取或者从casserver获取(webservice,http等远程方式),看你的角色权限配置在哪里)filterChainDefinitionMap.put("/user", "authc");//4.登录过的不拦截filterChainDefinitionMap.put("/**", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);}}

4.开发过程中遇到的坑

a.一般单点登录系统设计,会有一个CAS服务器,一个唯一的登录入口系统UC,还有多个子系统service1,service2…集成到UC,在集成工程中,MyShiroCasRealm 和ShiroCasConfig 代码一模一样,当时做的时候这里费了一定的时间。

b.自定义cookie的时候,要注意domain域名设置,如果是单点登录,各个系统要设置相同的父域名public.com,否则会出现每进入一个子系统都会生成一个session, 也就是session没有实现共享,在退出登录系统后,子系统中用户还有残留,切换用户后发现登录系统用户正确,但是进入子系统中,用户是上次登录的用户。

       cookie.setDomain(“public.com”);

c.shiro集成了redis,利用myRedisCacheManager,将权限信息保存到redis中,实现了子系统中权限共享,比如按钮级别权限。

DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();dwsm.setCacheManager(myRedisCacheManager());// 指定 SubjectFactorydwsm.setSubjectFactory(new CasSubjectFactory());dwsm.setSessionManager(redisSessionManager());dwsm.setRealm(myShiroCasRealm);

d.shiro集成了redis,利用dwsm.setSessionManager(redisSessionManager());将session信息保存到redis中,实现了子系统中session共享,进入每个子系统都是同一个session。 浏览器cookie的value就是该session的ID。


5.end

springboot-shiro-cas-redis集成session共享,权限共享相关推荐

  1. 全程配图超清晰的Springboot权限控制后台管理项目实战第二期(Springboot+shiro+mybatis+redis)

    全程配图超清晰的Springboot权限控制后台管理项目实战第二期(Springboot+shiro+mybatis+redis) 众所周知,作为一个后端新手学习者,通过项目来学习,增长项目经验,是一 ...

  2. springboot+shiro+cas实现单点登录之shiro端搭建

    github:https://github.com/peterowang/shiro-cas 本文如有配置问题,请查看之前的springboot集成shiro的文章 1.配置ehcache缓存,在re ...

  3. json web token没有哪个成分_【分享项目】给你看看我们公司的登录认证是怎么做的?!(SpringBoot+Shiro+Token+Redis)...

    背景交代 以前项目中权限认证没有使用安全框架,都是在自定义filter中判断是否登录以及用户是否有操作权限的.最近开了新项目,搭架子时,想到使用安全框架来解决认证问题,spring security太 ...

  4. springboot shiro和freemarker集成之权限控制完全参考手册(跳过认证,登录由三方验证,全网首发)...

    本文主要考虑单点登录场景,登录由其他系统负责,业务子系统只使用shiro进行菜单和功能权限校验,登录信息通过token从redis取得,这样登录验证和授权就相互解耦了. 用户.角色.权限进行集中式管理 ...

  5. C#session共享+redis_Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享...

    精品推荐 国内稀缺优秀Java全栈课程-Vue+SpringBoot通讯录系统全新发布! Docker快速手上视频教程(无废话版)[免费] 作者:夜月归途 转载自: https://www.cnblo ...

  6. SpringBoot+Shiro学习(一):主要模块介绍

    这篇文章是我最近对SpringBoot+Shiro+mybatis+redis一个练手项目的记录. 我是按照慕课网的一篇课程+百度进行练手的 慕课课程 练手项目Github地址 跟着开涛学Shiro ...

  7. 基于springboot+shiro一套可落地实施安全认证框架整合

    前言 俗话说,兵马未动,粮草先行,万丈高楼平地起,一套切实可用的微服务框架是整个项目小组进行后续高效开发的保障,在前期微服务框架构建过程中,大体来说,主要考虑3个点: 技术选项,如果公司业务规模能够提 ...

  8. SpringBoot笔记:SpringBoot2.3集成SpringSession+nginx+redis实现session共享

    文章目录 Spring Session介绍 Redis集成 yml配置 依赖添加 redis存值查看 登录服务器查看redis的值 查询所有"spring:session:"开头的 ...

  9. 使用Shiro+Redis实现Session共享

    章节目录 1. 为什么要实现Session共享? 1.1 负载均衡 1.2 负载均衡中的Session问题 1.3 案例演示 2. Shiro架构 3. Shiro集成Redis 1. 为什么要实现S ...

  10. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例(转)...

    SpringBoot整合mybatis.shiro.redis实现基于数据库的细粒度动态权限管理系统实例 shiro 目录(?)[+] 前言 表结构 maven配置 配置Druid 配置mybatis ...

最新文章

  1. 3d模型 vv5_WEY VV5硬刚现代ix35!神仙颜值种草95后小伙
  2. 水题Kattis Temperature Confusion小学数学
  3. iview table 自定义列_基于VueJS的render渲染函数打造一款非常强大的IView 的Table组件...
  4. GRUB与Linux系统修复(第二版)
  5. 非对称卷积—Asymmetric Convolutions
  6. xlsx文件和csv文件的相互转化
  7. oracle12c常用新特性,开发者必读:Oracle12c新特性再总结
  8. MPUSH消息推送服务器搭建,MPUSH消息推送服務器搭建
  9. imageai--自动机器学习初体验
  10. 翻译: 巴菲特公式:睡觉比醒来更聪明
  11. 软件测试中的正交缺陷分析总结,正交缺陷分类(ODC)流程简介及应用经验分享(上)...
  12. python中优先级最高的运算符为_Python 运算符优先级
  13. [转]绝对地址和相对地址的区别,为什么要采用绝对地址?
  14. win10系统显示打印机未连接到服务器,解决win10提示“Windows无法连接到打印机”的方法...
  15. 【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-汇总 ( Chapter17-ChapterB )
  16. MATLAB深度学习(1) --- 想要做好深度学习?数据集是第一步
  17. 爱心表白代码HTML
  18. 2.1.2 Capturing HDR Videos(Advanced High Dynamic Range Imaging )
  19. 材料力学Ⅰ(第六版)第五章课后习题答案
  20. STM32F429图形加速器(DMA2D)

热门文章

  1. java名字转化为拼音_将中文姓名转换为拼音
  2. java并发增强工具_0318 guava并发工具
  3. px4源码----位置估算(position_estimator_inav_params.h)
  4. 通过二层交换机的局域网配置
  5. 联想换机助手_三星S换机助手
  6. atmega128 bootloader程序在IAR-AVR下 linker文件的配置及原因
  7. 高中计算机会考操作试题,高中信息技术会考(上机操作题要点)
  8. 浅谈一下workstation
  9. 分享淘宝利器飞天侠4.1至尊商业版 去除域名限制 绕过淘宝API直接采集
  10. 开源ITIL框架 php,分享|如何在 CentOS 7 上安装开源 ITIL 门户 iTOP