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

本文详细解析了在使用Springboot、Shiro、Mybatisplus等技术栈时遇到的CORS跨域问题,特别是在前后端分离场景下,如何在Shiro过滤器中正确处理OPTIONS预检请求及实现数据的正常传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目背景:

最近在做一个后台用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() {

    }
}

再次调试,可以了

<think>好的,用户现在遇到了后端接口userInfo/export找不到的问题。我需要先分析可能的原因,然后逐步引导用户排查。首先,用户之前询问了关于handleExport()方法的代码解释,现在可能是在实际使用中遇到了404错误或其他接口不可用的情况。 用户可能是开发者,或者是刚接触这个项目的新手,对后端路由配置不太熟悉。他们的真实需求是解决接口调用失败的问题,可能希望导出数据但遇到了阻碍。深层需求可能是想了解如何调试和解决这类常见的后端接口问题,而不仅仅是知道问题存在。 接下来,我应该考虑常见的导致接口不到的原因。首先检查URL是否正确,是否存在拼写错误或者路径错误。然后确认后端是否实际存在这个路由,并且是否处理了GET或POST请求。可能需要检查后端的路由配置文件,比如Spring Boot中的@GetMapping或@PostMapping,或者Node.js的Express路由设置。 另外,权限问题也可能导致404,比如用户没有访问该接口的权限,或者需要特定的请求头如Token问题(CORS)也可能导致前端无法访问接口,但通常会返回CORS错误而不是404。请求方法是否正确,比如应该用POST却用了GET,或者相反。 用户可能需要逐步排查,比如先测试接口Postman中的可用性,查看后端日志是否有请求到达,检查网络请求的详细信息,确认代理配置是否正确(尤其是在开发环境中使用webpack代理时)。还有可能是项目结构问题,比如接口路径没有正确嵌套在父路径下,或者配置文件没有正确加载。 最后,给出一个总结的排查步骤,帮助用户系统地检查每个可能的问题点,并建议他们如何与后端团队协作解决问题。确保回答结构清晰,分点说明,方便用户一步步操作。</think>以下是针对接口 `userInfo/export` 找不到问题的系统性排查指南,按优先级排序: --- ### 一、基础检查阶段 1. **URL 完整性验证** - 检查是否包含 **基础路径**(如开发环境为 `/api/`,生产环境为 `/prod-api/`) - 完整路径可能实际为:`/api/userInfo/export` 或 `/prod-api/userInfo/export` - ▶️ 打开浏览器开发者工具(F12),在 Network 面板查看实际请求的完整 URL 2. **请求方法匹配性验证** - 确认前端使用的 **HTTP 方法**(GET/POST)与后端定义一致 - ▶️ 常见错误:后端要求 POST 但前端发送 GET - ▶️ 检查后端代码注解(示例): ```java // Spring Boot 示例 @PostMapping("/userInfo/export") // 明确要求 POST 方法 public void export() { ... } ``` --- ### 二、后端配置排查 3. **路由映射检测** - 确认接口是否被正确注册到路由系统中 - ▶️ 重点检查位置: - Spring Boot:`@RestController` 类是否包含在包扫描路径 - Node.js:Express 路由是否被正确挂载到主应用 - Django:`urls.py` 中是否注册该路径 4. **权限拦截分析** - 检查是否被 **安全框架拦截**(常见于 Spring Security/Shiro) - ▶️ 典型表现:控制台出现 `403 Forbidden` 而非 404 - ▶️ 临时关闭权限验证测试接口可达性 5. **配置验证(CORS)** - 检查响应头是否包含: ```http Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET,POST ``` - ▶️ 开发环境下可通过浏览器控制台直接观察 CORS 错误提示 --- ### 三、进阶调试手段 6. **后端日志追踪** - 强制打印请求日志(推荐使用拦截器) - ▶️ Spring Boot 示例:添加日志拦截器 ```java @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { System.out.println("收到请求路径:" + ((HttpServletRequest)request).getRequestURI()); chain.doFilter(request, response); } ``` 7. **接口存活测试** - 使用 Postman 直接访问(绕过前端) ```http POST http://localhost:8080/api/userInfo/export Content-Type: application/json { "pageNum": 1, "pageSize": 20 } ``` - ▶️ 若 Postman 可访问但前端报错,则问题出在 **前端请求构造** --- ### 四、特殊场景排查 8. **路径嵌套问题** - 检查父级路径是否冲突(常见于多模块开发) - ▶️ 错误示例: ```java @RestController @RequestMapping("system") public class UserController { @GetMapping("userInfo/export") // 实际路径为 /system/userInfo/export public void export() { ... } } ``` 9. **代理配置验证** - 检查前端工程配置文件(vue.config.js/webpack.config.js) - ▶️ 开发环境代理示例: ```javascript devServer: { proxy: { '/api': { target: 'http://localhost:8080', // 确保与后端端口一致 changeOrigin: true } } } ``` --- ### 五、终极解决方案 ```mermaid graph TD A[接口404] --> B{是否本地开发?} B -->|是| C[检查代理配置] B -->|否| D[检查生产环境Nginx配置] C --> E[确认后端服务已启动] D --> F[检查部署包版本] E --> G[查看后端控制台日志] F --> H[回滚最近部署] ``` 建议将以下信息提供给后端开发人员: 1. 请求的完整 URL(含端口) 2. 请求Headers 截图 3. 后端服务启动日志片段 4. 测试用的 Postman 请求示例
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值