zoukankan      html  css  js  c++  java
  • 21.Shiro在springboot与vue前后端分离项目里的session管理

    1.前言

    当决定前端与后端代码分开部署时,发现shiro自带的session不起作用了。

    然后通过对请求head的分析,然后在网上查找一部分解决方案。

    最终就是,登录成功之后,前端接收到后端传回来的sessionId,存入cookie当中。

    之后,前端向后端发送请求时,请求Head中都会带上这个sessionid。

    后端代码通过对这个sessionid的解析,拿到正确的session。

    2.代码改造

    (1)后端代码改造

    1. 添加CustomSessionManager.java

      /**
       * 类的详细说明
       *
       * @author 郭广明
       * @version 1.0
       * @Date 2018/11/3014:56
       */
      public class CustomSessionManager extends DefaultWebSessionManager {
      
          /**
           * 获取请求头中key为“Authorization”的value == sessionId
           */
          private static final String AUTHORIZATION ="Authorization";
      
          private static final String REFERENCED_SESSION_ID_SOURCE = "cookie";
      
          /**
           *  @Description shiro框架 自定义session获取方式<br/>
           *  可自定义session获取规则。这里采用ajax请求头 {@link AUTHORIZATION}携带sessionId的方式
           */
          @Override
          protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
              // TODO Auto-generated method stub
              String sessionId = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
              if (StringUtils.isNotEmpty(sessionId)) {
                  request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
                  request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
                  request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
                  return sessionId;
              }
              return super.getSessionId(request, response);
          }
      
      }
      
    2. 改造ShiroConfig.java

      @Configuration
      public class ShiroConfig {
      
          @Autowired
          private UserService userService;
      
          @Bean
          public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
              ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
      
              // 必须设置 SecurityManager
              shiroFilterFactoryBean.setSecurityManager(securityManager);
      
              // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
              shiroFilterFactoryBean.setLoginUrl("/login");
      
              // 拦截器.
              Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
              // 配置不会被拦截的链接 顺序判断
              filterChainDefinitionMap.put("/static/**", "anon");
              filterChainDefinitionMap.put("/doLogin", "anon");
              filterChainDefinitionMap.put("/swagger-resources", "anon");
              filterChainDefinitionMap.put("/v2/api-docs", "anon");
              filterChainDefinitionMap.put("/webjars/**", "anon");
              filterChainDefinitionMap.put("/swagger-ui.html", "anon");
      
              // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
              // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
              filterChainDefinitionMap.put("/**", "anon");
      
              shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
              System.out.println("Shiro拦截器工厂类注入成功");
              return shiroFilterFactoryBean;
          }
      
          /**
           * 注入MyRealm
           * @return
           */
          @Bean
          public SecurityManager securityManager() {
              DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
              // 设置realm.
              securityManager.setSessionManager(sessionManager());
              securityManager.setRealm(myShiroRealm());
              return securityManager;
          }
      
          /**
           * 配置注解
           * @param securityManager
           * @return
           */
          @Bean
          public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
              AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor
                      = new AuthorizationAttributeSourceAdvisor();
              authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
              return authorizationAttributeSourceAdvisor;
          }
      
          @Bean
          public MyRealm myShiroRealm() {
              return new MyRealm(userService);
          }
      
          @Bean("sessionManager")
          public SessionManager sessionManager(){
              CustomSessionManager manager = new CustomSessionManager();
      		/*使用了shiro自带缓存,
      		如果设置 redis为缓存需要重写CacheManager(其中需要重写Cache)
      		manager.setCacheManager(this.RedisCacheManager());*/
      
              manager.setSessionDAO(new EnterpriseCacheSessionDAO());
              return manager;
          }
      
      }
      

    (2)前端代码改造

    1. 添加CookieUtil.js

      export default {
      	setCookie: (name,value,days) =>{
      		var d = new Date;
      		d.setTime(d.getTime() + 24*60*60*1000*days);
      		window.document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString();
      	},
      	getCookie: name =>{
      		var v = window.document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
      		return v ? v[2] : null;
      	},
      	delCookie: name =>{
      		this.setCookie(name, '', -1); //将时间设置为过去时,立即删除cookie
      	}
      	
      }
      
    2. 改造HttpUtil.js

      import axios from 'axios'
      import doCookie from '@/util/cookieUtil'
      
      axios.defaults.headers.common['Authorization'] = doCookie.getCookie("SESSIONID")
      axios.defaults.baseURL = 'http://127.0.0.1:8080'
      
      
      /**
       * Get请求
       */
      export function get(url, callback){
          axios.get(url)
          .then(function (response) {
              if(response.data.length==0 || response.data==null) {
                  callback(null,true)
              } else {
                  callback(response.data,true)
              }
          })
          .catch(function (error) {
              callback(null,false)
          })
      }
      
      export function remove(url, callback){
          axios.delete(url)
          .then(function (response) {
              if(response.data.length==0 || response.data==null) {
                  callback(null,true)
              } else {
                  callback(response.data,true)
              }
          })
          .catch(function (error) {
              callback(null,false)
          })
      }
      
      export function post(url, data, callback){
          axios.post(url,data)
          .then(function (response) {
              if(response.data.length==0 || response.data==null) {
                  callback(null,true)
              } else {
                  callback(response.data,true)
              }
          })
          .catch(function (error) {
              callback(null,false)
          })
      }
      
      export function put(url, data, callback){
          axios.put(url,data)
          .then(function (response) {
              if(response.data.length==0 || response.data==null) {
                  callback(null,true)
              } else {
                  callback(response.data,true)
              }
          })
          .catch(function (error) {
              callback(null,false)
          })
      }
      
      
      export default {
          get,
          post,
          put,
          remove,
      }
      
  • 相关阅读:
    《构建之法》第8、9、10章 读后感
    [团队项目]SCRUM项目6.0 7.0 (新)
    [团队项目]SCRUM项目5.0
    [团队项目]SCRUM项目4.0
    [团队项目] Scrum 项目 3.0 SCRUM 流程的步骤2: Spring 计划
    [操作系统]实验三 进程调度模拟程序
    [团队项目] Scrum 项目 2.0 产品BACKLOG
    复利计算的总结
    复利/单利计算程序进度0321更新
    0312 复利计算器2.0 运行与介绍
  • 原文地址:https://www.cnblogs.com/TimerHotel/p/springboot21.html
Copyright © 2011-2022 走看看