springboot,shiro跨域CORS请求,拿不到headers中的token值解决

项目背景:

最近在做一个后台用Spring boot、Shiro、Mybatis plus 、Oauth2,前台用layui的项目.前端在调后台接口的时候需要在浏览器中的headers头中添加token和userId的值(根据业务不同可能传值不一样),后台有一个过滤器,获取到headers中的token和userId,并去验证token是否在有效期内,在进行其他操作,在这个过程中,shiro的过滤器中一直接收不到token和userId的值,并且前端会报跨域问题

前端错误信息
在这里插入图片描述

后端拦截器一直接收不到token和userId信息
在这里插入图片描述

但这个时候尝试用postman(postman不会出现跨域问题)发送试试,结果可以收到值,WTF,开始考虑的原因可能是token和userId没有放入headers中,后来通过仔细看了下没问题啊(下图)

在这里插入图片描述
在这里插入图片描述

为什么不发送值呢。仔细又去看了CROS的介绍。原来CROS复杂请求时会先发送一个OPTIONS请求,来测试服务器是否支持本次请求,这个请求时不带数据的,请求成功后才会发送真实的请求。所以前面那个只发送key的问题是要确认服务器支不支持接收这个headers。所以每次获取不到数据的请求都是OPTIONS请求。所以我们要做的就是把所有的OPTIONS请求统统放行。

做法是在 StatelessAuthcFilter(自定义的过滤器) 中继承AccessControlFilter(Shiro自带的过滤器) 并重写其中的 preHandler 方法。 代码如下:

    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpRequest = WebUtils.toHttp(request);
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpResponse.setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"));
            httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
            //  httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
            httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
            httpResponse.setStatus(HttpStatus.OK.value());
            return false;
        }
        return super.preHandle(request, response);
     }?

这个时候还没有完全解决问题,上面步骤完成后,第一次OPTIONS请求成功,第二次真实请求也发送成功(状态为200),但是response里面没有数据,此时需要再次添加一个CrosFilter类,如下

package com.welsee.shiro;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CorsFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("Origin"));
        httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}

再次调试,可以了

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring BootShiro ,可以通过自定义过滤器来解决跨域问题。具体步骤如下: 1. 创建自定义跨域过滤器 创建一个类,继承 org.apache.shiro.web.filter.authc.FormAuthenticationFilter,实现 doFilterInternal 方法。代码如下: ```java public class CorsAuthenticationFilter extends FormAuthenticationFilter { @Override protected void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { HttpServletResponse httpServletResponse = (HttpServletResponse) response; HttpServletRequest httpServletRequest = (HttpServletRequest) request; // 允许跨域访问的域名 String[] allowedOrigins = {"http://localhost:8080"}; // 允许的请求类型 String allowedMethods = "GET,POST,PUT,DELETE,OPTIONS"; // 允许的头信息 String allowedHeaders = "Content-Type, Authorization"; httpServletResponse.setHeader("Access-Control-Allow-Origin", String.join(",", allowedOrigins)); httpServletResponse.setHeader("Access-Control-Allow-Methods", allowedMethods); httpServletResponse.setHeader("Access-Control-Allow-Headers", allowedHeaders); // 如果是预检请求,直接返回成功 if (httpServletRequest.getMethod().equalsIgnoreCase("OPTIONS")) { httpServletResponse.setStatus(HttpServletResponse.SC_OK); return; } super.doFilterInternal(request, response, chain); } } ``` 这里的 allowedOrigins 配置是允许的跨域地址,allowedMethods 配置是允许的 HTTP 方法,allowedHeaders 配置是允许的 HTTP 头信息。如果收到的请求是预检请求,直接返回成功即可。 2. 在 Shiro 配置添加自定义过滤器 在 Shiro 的配置文件添加自定义过滤器。例如: ```java @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); // ... Map<String, Filter> filters = new LinkedHashMap<>(); filters.put("corsAuthenticationFilter", new CorsAuthenticationFilter()); filterFactoryBean.setFilters(filters); // ... return filterFactoryBean; } ``` 这里将自定义过滤器 CorsAuthenticationFilter 添加到了 Shiro 的过滤器链。 3. 配置 Spring Boot跨域设置 在 Spring Boot 的配置文件添加 CORS 的配置,跟上面的一样。 这样配置完后,就可以跨域访问 Shiro 的接口了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值