Springboot拦截器中跨域失效的问题、同一个接口传入参数不同,一个成功,一个有跨域问题、拦截器和@CrossOrigin和@Controller

Springboot拦截器中跨域失效的问题

一、概述

1、具体场景

起因:

  • 同一个接口,传入不同参数进行值的修改时,一个成功,另一个竟然失败,而且是跨域问题
  • 拦截器内的request参数调用getHeader方法时,获取不到前端设置的请求头,且浏览器显示有,但是后端输出后只有对于的key,而且key变成了access-control-request-headers的value

同一个接口不同参数错误展示:
在这里插入图片描述


前端代码展示:

在这里插入图片描述


浏览器请求头显示:
在这里插入图片描述


后端获取request的header参数显示:

全是null

在这里插入图片描述

输出headers:

{sec-fetch-mode=cors, referer=http://localhost:8080/, sec-fetch-site=cross-site, accept-language=zh-CN,zh;q=0.9, origin=http://localhost:8080, access-control-request-method=POST, accept=*/*, host=127.0.0.1:8099, access-control-request-headers=content-type,headeruserid,headerusertoken, connection=keep-alive, accept-encoding=gzip, deflate, br, user-agent=Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36, sec-fetch-dest=empty}

变成了这样:access-control-request-headers=content-type,headeruserid,headerusertoken,

2、背景

前端:

  1. 是个uniapp项目,只会调,不会写,未设置跨域

后端:

  1. spring boot项目
  2. 后端使用了@CrossOrigin(origins = "*"),进行了简单的跨域设置
  3. 后端使用了拦截器进行拦截认证

3、尝试改bug

发现前端的参数key,浏览器的参数key和后端的参数key大小写不一致:

  • 修改了多次,且尝试了多次,无效果
String userId = request.getHeader("headerUserId");
String userId2 = request.getHeader("HeaderUserId");
String userId3 = request.getHeader("Headeruserid");

在这里插入图片描述

尝试前端添加跨域:

  • 统一设置跨域请求头,不会,只会小改
  • 前端添加:Access-Control-Allow-Origin: *,无效,后面认真看才发现这是响应头,不是请求头,sha呗了

尝试后端的拦截器内添加@CrossOrigin(origins = “*”)、具体拦截方法内给响应参数添加响应头:

  • 无效

重启前端项目、清除浏览器缓存、清除idea缓存、rebuild项目、重新运行:

  • 无效

二、解决办法

试了很多方法,慢慢的就定位了问题:

  • 前端设置的请求头,浏览器可以接收,而且具体显示,那就不是前端的问题
  • 后端试了很多次,拦截器获取的request header 的key和value还是null
  • 如果取消拦截器,正常可以获取
  • 那么可能是拦截器的问题,我的@CrossOrigin(origins = "*")加在我的接口上,但是拦截器先执行,如果没用通过那么直接返回,根本到不了我的接口,也就到不了我接口上的@CrossOrigin(origins = "*"),那就没用跨域了
  • 但是我尝试再拦截器内的方法中手动给response响应添加跨域的代码,如下,但是还是无效
// 支持跨域
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods",
"GET,POST,PUT,DELETE,OPTIONS");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Token");
response.setHeader("Access-Control-Allow-Credentials", "true");

后面查询跨域的请求流程:

跨域请求的流程通常分为两个阶段:预检请求(Preflight Request)和实际请求。以下是跨域请求的一般流程:

  1. 预检请求阶段

    • 当浏览器检测到跨域请求时(例如请求方法不是简单请求方法、请求包含自定义的请求头等),会首先发送一个预检请求(OPTIONS请求)给服务器。
    • 预检请求的目的是询问服务器是否允许实际请求中包含特定的自定义请求头字段和请求方法。
    • 预检请求会包含一些特定的请求头,如Access-Control-Request-MethodAccess-Control-Request-Headers,用来询问服务器的允许范围。
    • 服务器收到预检请求后,根据预检请求中的信息判断是否允许实际请求,然后发送适当的CORS响应头给浏览器。
  2. 实际请求阶段

    • 如果预检请求得到了服务器的允许(即服务器返回了合适的CORS响应头),浏览器将发送实际的请求给服务器。
    • 实际请求中包含了正常的请求方法(例如GET、POST、PUT等)、请求头和请求体等信息。
    • 服务器收到实际请求后,会处理请求并返回相应的响应给浏览器。

下图展示了跨域请求的流程:

     +-------------+         +-------------+
     |    Browser  |         |    Server   |
     +-------------+         +-------------+
           |                        |
           | 1. 发送预检请求        |
           +----------------------->|
           |                        |
           | 2. 接收预检响应        |
           |<-----------------------+
           |                        |
           | 3. 发送实际请求        |
           +----------------------->|
           |                        |
           | 4. 接收实际响应        |
           |<-----------------------+

总的来说,跨域请求的流程就是浏览器先发送预检请求询问服务器是否允许跨域请求,然后根据服务器的响应决定是否发送实际请求。如果预检请求得到了服务器的允许,浏览器才会发送实际的请求。

跟着这个OPTIONS请求查找:

发现,只需要我把这个请求过滤掉即可,让它可以实际请求,使得我的自定义请求头 - 特定的请求头(access-control-request-headers=content-type,headeruserid,headerusertoken)可以接收到我就可以进行判断了。

if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
    return true;
}

有效果,解决了。

在这里插入图片描述

三、拓展

此处是使用的@CrossOrigin(origins = "*")注解同时过滤掉OPTIONS请求实现了跨域

还可以通过只设置一个跨域过滤器解决跨域问题

下列方法转载于博客园作者小泉哥

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 全局跨域配置类
 * 跨域请求的配置,允许所有来源的跨域请求
 * 
 * 跨域请求流程:
 * 1. 浏览器发送预检请求(OPTIONS请求)给服务器,询问是否允许实际请求中包含特定的自定义请求头字段和请求方法。
 * 2. 服务器根据预检请求的信息判断是否允许实际请求,发送适当的CORS响应头给浏览器。
 * 3. 如果预检请求得到了服务器的允许,浏览器发送实际的请求给服务器。
 * 4. 服务器收到实际请求后,处理请求并返回相应的响应给浏览器。
 * 
 * 注:当设置allowCredentials为true时,Access-Control-Allow-Origin响应头不能使用通配符"*",而是必须明确指定允许的来源。
 * 
 * @author red-velvet
 * @since 2024/2/8
 */
@Configuration
public class GlobalCorsConfig {

    /**
     * 配置CorsFilter
     * @return CorsFilter
     */
    @Bean
    public CorsFilter corsFilter() {
        // 创建CorsConfiguration对象,配置CORS跨域规则
        CorsConfiguration config = new CorsConfiguration();
        // 允许所有来源的跨域请求
        config.addAllowedOrigin("*");
        // 允许携带凭据(例如Cookie)
        config.setAllowCredentials(false);
        // 允许所有请求方法的跨域请求
        config.addAllowedMethod("*");
        // 允许所有请求头的跨域请求
        config.addAllowedHeader("*");

        // 创建UrlBasedCorsConfigurationSource对象,注册CORS配置
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        // 创建CorsFilter对象,传入配置源
        return new CorsFilter(configSource);
    }
}
dCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        // 创建CorsFilter对象,传入配置源
        return new CorsFilter(configSource);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/379306.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理

文章目录 前言一、所需环境二、实现思路2.1. 定义了LeNet网络模型结构&#xff0c;并训练了20次2.2 以txt格式导出训练结果(模型的各个层权重偏置等参数)2.3 (可选)以pth格式导出训练结果&#xff0c;以方便后期调试2.4 C CUDA要做的事 三、C CUDA具体实现3.1 新建.cu文件并填好…

day29打卡

day29打卡 491. 非递减子序列 使用uset记录本层元素是否使用即可。 class Solution { public:vector<vector<int>> ret;vector<int> path;vector<vector<int>> findSubsequences(vector<int>& nums) {//不能排序&#xff0c;排序后…

股票K线简介

股票K线&#xff08;K-Line&#xff09;是用于表示股票价格走势的图形&#xff0c;主要由四个关键价格点组成&#xff1a;开盘价、收盘价、最高价和最低价。K线图广泛应用于股票市场技术分析中&#xff0c;它提供了丰富的信息&#xff0c;帮助分析师和投资者理解市场的行情走势…

【Linux】Shell编程

Shell编程 目录 Shell编程1.shell基础1.输入重定向 & 输出重定向2.管道3.特殊字符(3.1)通配符(3.2)引号(3.3)注释符(#) 4.别名5.命令历史history 2.Shell脚本Shell脚本的执行方式(1)为脚本文件加上可执行权限,然后在命令行直接输入shell脚本文件名执行。(2)sh shell脚本名(…

【RT-DETR进阶实战】利用RT-DETR进行视频划定区域目标统计计数

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 Hello,各位读者,最近会给大家发一些进阶实战的讲解,如何利用RT-DETR现有的一些功能进行一些实战, 让我们不仅会改进RT-DETR,也能够利用RT-DETR去做一些简单的小工作,后面我也会将这些功能利用PyQt或者是…

华清作业day56

SQLite特性&#xff1a; 零配置一无需安装和管理配置&#xff1b;储存在单一磁盘文件中的一个完整的数据库&#xff1b;数据库文件可以在不同字节顺序的机器间自由共享&#xff1b;支持数据库大小至2TB&#xff1b;足够小&#xff0c;全部源码大致3万行c代码&#xff0c;250KB…

boot::process::child::wait_until 线程不安全

最近在项目中需要多线程调用子程序。子程序可能工作时间很长&#xff0c;故用 boost::process::child::wait_until 来实现超时功能。 然而&#xff0c;多线程压力测试时&#xff0c;发现有可能导致 core dump。 经查证&#xff0c;是 boost::process::child::wait_until 的一个…

Office 2010下载安装教程,保姆级教程,附安装包和工具

前言 Microsoft Office是由Microsoft(微软)公司开发的一套基于 Windows 操作系统的办公软件套装。常用组件有 Word、Excel、PowerPoint、Access、Outlook等。 准备工作 1、Win7 及以上系统 2、提前准备好 Office 2010 安装包 安装步骤 1.鼠标右击【Office2010(64bit)】压缩…

U3D记录之FBX纹理丢失问题

今天费老大劲从blender建了个模型&#xff0c;然后导出进去unity 发现贴图丢失 上网查了一下 首先blender导出要改设置 这个path mode要copy 然后unity加载纹理也要改设置 这里这个模型的纹理load要改成external那个模式 然后就有了&#xff0c;另外这个导出还有好多选项可…

SSM框架,Spring-ioc的学习(上)

知识点引入 关于框架 框架( Framework )是一个集成了基本结构、规范、设计模式、编程语言和程序库等基础组件的软件系统&#xff0c;它可以用来构建更高级别的应用程序。框架的设计和实现旨在解决特定领域中的常见问题&#xff0c;帮助开发人员更高效、更稳定地实现软件开发目…

nginx upstream server主动健康检测模块ngx_http_upstream_check_module 使用和源码分析(中)

目录 6. 源码分析6.1 解析指令分析6.2 待检查的服务器的添加和状态查询6.3 本模块的进程初始化函数6.4 准备执行健康检测任务6.5 执行健康检测任务本篇对ngx_http_upstream_check_module的源码实现进行详细分析。 关于配置和使用部分可以查看上篇:nginx upstream server主动健…

[word] word中怎么插入另外一个word文档 #媒体#职场发展

word中怎么插入另外一个word文档 word中怎么插入另外一个word文档&#xff1f;有有些小伙伴在制作文档的时候&#xff0c;可能需要用到多个文档进行配合制作&#xff0c;今天小Q来给大家演示一下&#xff0c;插入Word文档的方法&#xff0c;插入其他类型文档的方法也是一样的。…

Backtrader 文档学习- Plotting

Backtrader 文档学习- Plotting 虽然回测是一个基于数学计算的自动化过程&#xff0c;还是希望实际通过可视化验证。无论是使用现有算法回测&#xff0c;还是观察数据驱动的指标&#xff08;内置或自定义&#xff09;。 凡事都要有人完成&#xff0c;绘制数据加载、指标、操作…

RedissonClient妙用-分布式布隆过滤器

目录 布隆过滤器介绍 布隆过滤器的落地应用场景 高并发处理 多个过滤器平滑切换 分析总结 布隆过滤器介绍 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是…

汇编笔记 01

小蒟蒻的汇编自学笔记&#xff0c;如有错误&#xff0c;望不吝赐教 文章目录 笔记编辑器&#xff0c;启动&#xff01;debug功能CS & IPmovaddsub汇编语言寄存器的英文全称中英对照表muldivandor 笔记 编辑器&#xff0c;启动&#xff01; 进入 debug 模式 debug功能 …

python-产品篇-游戏-象棋

文章目录 代码效果 代码 import pygame import time import constants from button import Button import pieces import computerclass MainGame():window NoneStart_X constants.Start_XStart_Y constants.Start_YLine_Span constants.Line_SpanMax_X Start_X 8 * Lin…

ChatGPT 变懒最新解释!或和系统Prompt太长有关

大家好我是二狗。 ChatGPT变懒这件事又有了最新解释了。 这两天&#xff0c;推特用户Dylan Patel发文表示&#xff1a; 你想知道为什么 ChatGPT 和 6 个月前相比会如此糟糕吗&#xff1f; 那是因为ChatGPT系统Prompt是竟然包含1700 tokens&#xff0c;看看这个prompt里面有多…

测试管理_利用python连接禅道数据库并自动统计bug数据到钉钉群

测试管理_利用python连接禅道数据库并统计bug数据到钉钉 这篇不多赘述&#xff0c;直接上代码文件。 另文章基础参考博文&#xff1a;参考博文 加以我自己的需求优化而成。 统计的前提 以下代码统计的前提是禅道的提bug流程应规范化 bug未解决不删除bug未关闭不删除 db_…

Springboot+vue的社区智慧养老监护管理平台设计与实现(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的社区智慧养老监护管理平台设计与实现&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的社区智慧养老监护管理平台设…

人工智能专题:量子计算云平台功能模型、体系架构与能力分级研究报告

今天分享的是人工智能系列深度研究报告&#xff1a;《人工智能专题&#xff1a;量子计算云平台功能模型、体系架构与能力分级研究报告》。 &#xff08;报告出品方&#xff1a;量子信息网络产业联盟&#xff09; 报告共计&#xff1a;58页 国内外量子计算云平台发展现状 图1…