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,
      }
      
  • 相关阅读:
    改造vant日期选择
    css3元素垂直居中
    npm综合
    (转)网页加水印方法
    Mac下IDEA自带MAVEN插件的全局环境配置
    隐藏注册控件窗口
    High performance optimization and acceleration for randomWalk, deepwalk, node2vec (Python)
    How to add conda env into jupyter notebook installed by pip
    The Power of WordNet and How to Use It in Python
    背单词app测评,2018年
  • 原文地址:https://www.cnblogs.com/TimerHotel/p/springboot21.html
Copyright © 2011-2022 走看看