Springboot集成shiro,登录重定向跨域问题 您所在的位置:网站首页 java重定向跨域问题 Springboot集成shiro,登录重定向跨域问题

Springboot集成shiro,登录重定向跨域问题

2024-06-02 13:32| 来源: 网络整理| 查看: 265

🍅集成方式

项目采用了前后端分离的结构,前端使用的是vue框架,后端使用的是springboot框架,登录认证框架是shiro,同时使用了单点登录。

整个登录认证的逻辑:

通过shiro判断用户是否登陆了如果没有登录或者登录过期,通过shiro的配置跳转到指定的controller在controller中重定向到单点登录页面

🍇问题描述

当登录过期了前端先发送一个请求到接口Ashiro判断了用户已经登录过期了,返回状态码302,并让前端重新请求到接口B在接口B,返回状态码302,并让前端重新请求到单点登录地址前端重新请求这个单点登录地址浏览器判断单点登录地址和当前系统地址不是同一个,于是就出现跨域错误

🍈解决思路

这个问题在网上找了很多解决的办法都是通过解决跨域,比如使用注解@CrossOrigin,但是都没有生效。

后来思考了下,跨域是重定向和父页面不同的地址出现的,这个时候在后端怎么配置其实已经没有用了。

现在核心问题,当登录失效之后就不返回状态码302,而是直接调用退出登录接口,这样也能达到重新登录的目的。

🍉源码分析

为了解决这个问题,我们需要先研究一下shiro的源码如何来判断用户登录过期的,并且返回302重定向到新接口的。

在这里插入图片描述

通过上面的时序图可以看出最后调用的是AccesssControlFilter类的onPreHandle方法,这个方法调用了两个方法:isAccessAllowed和onAccessDenied。

isAccessAllowed:判断用户是否登录,如果登陆了直接返回了,如果没有登录就会执行第二个方法onAccessDenied:是否拒绝登录,在这里面就可以自定义一些返回值

public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue); }

从这里可以看出,如果我们想自己定义返回值的话就要重写这两个方法。

🍊解决办法

首先定义一个Filter,这个Filter继承AuthorizationFilter,然后重写了isAccessAllowed和onAccessDenied

在onAccessDenied中Response就返回401,前端拿到这个401就请求退出接口

public class RefreshAuthorizationFilter extends AuthorizationFilter { private ISecurityService securityService; public RefreshAuthorizationFilter(ISecurityService securityService) { this.securityService = securityService; } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { return securityService.isLogin(); } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { response.getWriter().write("401"); return false; } } 使用配置将Filter加入Filter链中,并且加上@Primary注解,这样优先级才会优先执行。 @Primary @Component public class RefreshALoginConfig extends ALoginConfig { @Autowired private ISecurityService securityService; @Override protected void addFilters() { addFilter("restartRefresh", new RefreshAuthorizationFilter(securityService)); } protected void initFilterChainDefinitions() { filter("/api/**", "restartRefresh"); } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有