前后端分离实现登录拦截

一.认证方案

1.Session
利用Session我们可以管理用户状态:

  • 服务器接受第一个请求时候,生成session对象,并通过响应头告诉客户端在cookie中放入sessionId
  • 客户端之后发送请求时,会带上包含sessionId的cookie
  • 服务器通过sessionId获取session,进而得到当前的状态
  • 每次客户端访问服务端带上sessionId即可

2.客户端存储方案

特性cookielocalStoragesessionStorage
生命周期一般由服务器生成,可设置失效时间。如果在浏览器端生成cookie,默认是关闭浏览器后失效除非被清除,否则永久保存仅在当前会话下有效,关闭页面或浏览器后被清除
数据大小4K左右一般为5MB一般为5MB
通信方式每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题仅在客户端(即浏览器)中保存,不参与和服务器的通信同 localStorage

二.为什么需要前后端拦截

之前前端拦截的思路是:

  1. 判断的路径是否需要登录;如果需要,判断store里面有没有存储user信息
  2. store有放行,没有就要跳到登录页面

这样是不安全的,我们可以在控制台输入

window.localStorage.setItem('user', JSON.stringify({"name":"哈哈哈"}));

从而去伪造,访问任何一个页面了。
所以
要实现靠谱的拦截,由后端验证用户登录状态,前端带上sessionId发送请求交由后端认证。

三.前后端拦截

3.1后端拦截

默认情况下,跨域的cookie是被禁止的,需要两边都要设置。跨域情况下会先发出一个options请求试探,这个请求是不带cookie信息的,所以shiro无法获取到sessionId

public class LoginInterceptor  implements HandlerInterceptor{

    @Override
    public boolean preHandle (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        // 放行 options 请求,否则无法让前端带上自定义的 header 信息,导致 sessionID 改变,shiro 验证失败
        if (HttpMethod.OPTIONS.toString().equals(httpServletRequest.getMethod())) {
            httpServletResponse.setStatus(HttpStatus.NO_CONTENT.value());
            return true;
        }

        Subject subject = SecurityUtils.getSubject();
        // 使用 shiro 验证
        if (!subject.isAuthenticated()) {
            return false;
        }
        return true;
    }

}
这里记录一下,我把这段代码屏蔽,也可以用。现在暂时不知道是什么原因。

SpringMVC配置允许跨域

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedOrigins("http://localhost:8080")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .allowedHeaders("*")
    }

3.2前端拦截

在main.js加上

axios.defaults.withCredentials = true

为了防止伪造参数,绕过前端路由限制,在每个页面钱都向后端发送一个请求,目的是经由拦截器验证服务端的登录状态,防止上述情况的发生。

router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth) {
      if (store.state.user) {
        axios.get('/authentication').then(resp => {
          if (resp.data) next()
        })
      } else {
        next({
          path: 'login',
          query: {redirect: to.fullPath}
        })
      }
    } else {
      next()
    }
  }
)

三.感谢

学习参考https://learner.blog.csdn.net/article/details/102788866

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值