21.Shiro在springboot与vue前后端分离项目里的session管理

可莉
• 阅读 1068

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,
    }
    
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
springboot2之优雅处理返回值
前言最近项目组有个老项目要进行前后端分离改造,应前端同学的要求,其后端提供的返回值格式需形如{"status":0,"message":"success","data":{}}方便前端数据处理。要实现前端同学这个需求,其实也挺简单的,
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这