Filter servlet interceptor 的执行顺序问题

背景

最近在做一个移动端h5项目的后端应用,接口联调时前端反应说登录有问题,先简单介绍一下我们的权限实现,jwt加spring security,使用redis做的session中心存放token。

1.前端请求登录接口,核对成功返回用户信息和token,同时将此信息保存于redis中
2.访问后端接口需要将token保存于header中,请求先经过安全Filter,会从token中解析出subject,然后去redis中查询看是否存在对应token
3.token相同则继续往下执行,token不同则说明登录已过期,返回401

具体情况是登录成功进入数据页面之后就会请求初始数据,但是请求初始数据时就会返回401,提示未登录然后跳转回登录页面,出现问题第一时间肯定是想办法甩锅,于是马上用postman进行接口自测,果然,postman测接口一切正常。怀疑是不是前端vue的状态管理有问题导致传的token不对,和redis中查到的token不同导致的,然而经过核对,传的的确是登录接口返回的token。锅又回到了我这边。

解决过程

涉及到公司封装的底层,唯一的解决办法就是debug源码
在这里插入图片描述
发现,此处getSession时的确返回的是null,进入方法
在这里插入图片描述
发现determinKey方法,里面使用spring的mobile的一个框架,此处的用途是将移动端用户登录和浏览器端用户登录区分出来,用不同的前缀,实现独立登录互不影响的效果,代码如下
在这里插入图片描述
在写session和读session的时候都会调用到此方法,debug一遍之后,逐渐发现不对劲,在登录成功写session之后,DeviceUtils.getCurrentDevice(request)返回的对象是MOBILE,是不为空的,但是在读session时,获取到的device却是为null的,只好再进入getCurrentDevice方法一探究竟,代码如下
在这里插入图片描述
是去request的域中获取currentDevice时取不到值导致的,那么什么时候往里面写的这个属性呢?网上一查,原来是在spring的一个拦截器中实现的

在这里插入图片描述
继续追寻
在这里插入图片描述
在这里插入图片描述
来到了springMVC最核心的servlet类中,发现请求数据的接口根本执行不到这里来,没有执行该拦截器,所以读session时也就获取不到device对象,那么为什么会不执行呢,上网一查,恍然大悟,原来是filter、servlet、interceptor之间的执行顺序造成,之所以登录能成功,是因为登录接口是无需权限验证的,绕过filter之后执行了拦截器的内容,写入了设备相关信息,在写session时会根据设备类型用不同的前缀存,但在读session时,因为filter比拦截器先执行,所以读不到设备信息,便会用默认的浏览器前缀的key去查session,所以便查不到session,返回401

解决

既然是顺序问题,于是便把判断客户端类型的逻辑迁移到权限Filter之前,读session时即可能争取获得session前缀

总结

执行顺序: Filter => Interceptor => Controller

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值