集成sa-token前后端分離部署配置corsFliter解決跨域失效的真正原因

文章目錄

  • 1.前言
  • 2.問題復現
  • 3.解決方法
    • 3.1 方式一:后端修改CorsFilter源碼
    • 3.2 方式二:前端禁用或移除瀏覽器referrer-policy引用者策略
  • 4.總結

1.前言

????緣由請參看下面這篇文章:sa-token前后端分離解決跨域的正確姿勢

https://mp.weixin.qq.com/s/96WbWL28T5_-xzyCfJ7Stg
https://blog.csdn.net/qq_34905631/article/details/140233780?spm=1001.2014.3001.5501

????這篇文章雖然經過n多次嘗試找到了正確的姿勢,但是問題的根本原因沒有找到,然后我就經過一些思考和探索,我想這個跨域能不能在本地模擬出來,然后起就去找了項目前端人員老王,然后確實模擬出本地跨域,在項目中將之前sa-token前后端分離解決跨域的正確姿勢文章中的SimpleCORSFilter注釋之后進行了問題復現。

2.問題復現

?????spring5.2.15.RELEASE官方mvc的跨域配置如下:

https://docs.spring.io/spring-framework/docs/5.2.15.RELEASE/spring-framework-reference/web.html#mvc-cors-intro

????按照上面鏈接官方的一種方式,然后新增了一個CustomCorsFilter類如下:

package xxxx.config;import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomCorsFilter extends CorsFilter {public CustomCorsFilter() {super(corsConfigurationSource());}private static CorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.addAllowedOrigin("*"); // 允許訪問的域名,例如 http://localhost:8080configuration.addAllowedHeader("*"); // 允許所有請求頭configuration.addAllowedMethod("*"); // 允許所有請求方法configuration.setAllowCredentials(true);UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;}}

????該CustomCorsFilter的配置寫法我搞的一個項目中配置驗證過是有效的,但是在最近做的一個項目中使用這個CustomCorsFilter類配置到項目中解決跨域缺沒有用,難道是這種配置失效了嗎?在上面sa-token前后端分離解決跨域的正確姿勢文章中配置了CustomCorsFilter類驗證確實是失效了,這個問題真的是讓人百思不得其解,當我在項目中重新配置好CustomCorsFilter類之后(SimpleCORSFilter需要注釋,因為這個SimpleCORSFilter進過驗證時可以行的),緊接著把項目本地跑起來之后,前端模擬跨域請求,我在CorsFilter類的如下代碼打上斷點:

   @Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);boolean isValid = this.processor.processRequest(corsConfiguration, request, response);//關鍵就是這里,在這里打上斷點if (!isValid || CorsUtils.isPreFlightRequest(request)) {return;}filterChain.doFilter(request, response);}

????CorsUtils.isPreFlightRequest方法上也打上斷點:

	public static boolean isPreFlightRequest(HttpServletRequest request) {return (HttpMethod.OPTIONS.matches(request.getMethod()) &&request.getHeader(HttpHeaders.ORIGIN) != null &&request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);}

????然后斷點截圖如下:

????登錄接口是一個http加域名的復雜跨域請求會發送一個預檢測請求(OPTIONS請求)

cors調試圖片2

????在集成了sa-token的項目中OncePerRequestFilter的doFilterInternal方法打上斷點,發現有如下過濾器:

cors調試圖片2

????可以看到上面我們自定一的CustomCorsFilter是在最先執行的,sa-token相關的兩個filter:saPathCheckFilterForServlet和SaServletFilter都是后面才執行的,所以之前的其他猜想都得到了很好的證實,當斷點走到下面這里CorsFilter的doFilterInternal方法中:

       //關鍵就是這里,在這里打上斷點if (!isValid || CorsUtils.isPreFlightRequest(request)) {return;}

????問題就出在如下代碼:

CorsUtils.isPreFlightRequest(request)

????這行代碼返回了true,就return了,后面的所有過濾器都沒有執行,所以請求不到接口,瀏覽器還是在報跨域的問題,然后我就調試了CorsUtils.isPreFlightRequest(request)這行代碼,發現是復雜請求跨域發了預檢測請求(OPTIONS請求)之后Orgin會被設置了一個莫名奇妙的是:

http://localhost:3000

????這個就很奇怪了,然后我就找了前端同事老王幫看了下,這個值是哪里設置的,然后發現如下:

cors調試圖片3

????前端沒有設置Orgin,只是設置了如下參數:

//設置axios跨域訪問
axios.defaults.withcredentials = true // 設置cross跨域 并設置訪問權限 允許跨域攜帶cookie信息axios.defaults.crossDomain=true //設置axios跨域的配置

????上面的圖片只有一個Referer的值跟Orgin的值不謀而合,難道這真的只是一個巧合,于是我參看了如下文章:

https://blog.csdn.net/qq_55316925/article/details/128571809

????給我很多的思路,那我想了一下,居然這樣,后端配置的CustomCorsFilter是生效了的,那可不可以改CorsFilter源碼,于是就嘗試了下面兩種方式,進過我和前端老王的驗證,這兩種方式都是可行的,任選一種都是可以解決cors跨域問題。

3.解決方法

3.1 方式一:后端修改CorsFilter源碼

????后端修改CorsFilter源碼

????在項目下src.main.java下新增一個org.springframework.web.filter的包

????然后將CorsFilter的源碼拷貝出來,放到上面新建的這個org.springframework.web.filter的包下,就可以修改CorsFilter的源碼了,

/** Copyright 2002-2019 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.springframework.web.filter;import java.io.IOException;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.util.Assert;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsProcessor;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.DefaultCorsProcessor;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;/*** {@link javax.servlet.Filter} that handles CORS preflight requests and intercepts* CORS simple and actual requests thanks to a {@link CorsProcessor} implementation* ({@link DefaultCorsProcessor} by default) in order to add the relevant CORS* response headers (like {@code Access-Control-Allow-Origin}) using the provided* {@link CorsConfigurationSource} (for example an {@link UrlBasedCorsConfigurationSource}* instance.** <p>This is an alternative to Spring MVC Java config and XML namespace CORS configuration,* useful for applications depending only on spring-web (not on spring-webmvc) or for* security constraints requiring CORS checks to be performed at {@link javax.servlet.Filter}* level.** <p>This filter could be used in conjunction with {@link DelegatingFilterProxy} in order* to help with its initialization.** @author Sebastien Deleuze* @since 4.2* @see <a href="https://www.w3.org/TR/cors/">CORS W3C recommendation</a>*/
public class CorsFilter extends OncePerRequestFilter {private final CorsConfigurationSource configSource;private CorsProcessor processor = new DefaultCorsProcessor();/*** Constructor accepting a {@link CorsConfigurationSource} used by the filter* to find the {@link CorsConfiguration} to use for each incoming request.* @see UrlBasedCorsConfigurationSource*/public CorsFilter(CorsConfigurationSource configSource) {Assert.notNull(configSource, "CorsConfigurationSource must not be null");this.configSource = configSource;}/*** Configure a custom {@link CorsProcessor} to use to apply the matched* {@link CorsConfiguration} for a request.* <p>By default {@link DefaultCorsProcessor} is used.*/public void setCorsProcessor(CorsProcessor processor) {Assert.notNull(processor, "CorsProcessor must not be null");this.processor = processor;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);boolean isValid = this.processor.processRequest(corsConfiguration, request, response);//修改的源碼是將CorsUtils.isPreFlightRequest(request)這行代碼移除,就是因為復雜請求跨域發了預檢測請求,瀏覽器的referrer-policy引用者策略會攜帶一個值,后端處理之后會將這個值賦值給請求頭的Orgin屬性上,移除這行代碼之后就可以正常訪問到登錄接口了,前端也沒有報跨域了。if (!isValid) {return;}filterChain.doFilter(request, response);}}

3.2 方式二:前端禁用或移除瀏覽器referrer-policy引用者策略

????前端新增如下代碼 :禁用或者是移除referrer-policy`這個引用者策略

https://blog.csdn.net/qq_49810363/article/details/111036180

????新增代碼如下:

<meta name="referrer" content="never">

cors調試圖片4

????瀏覽器的referrer-policy引用者策略,也是為了安全考慮,我使用的瀏覽器是chrome瀏覽器

4.總結

????經過不斷地嘗試和摸索之后,對這個在項目中集成了sa-token后部署出現cors跨域的問題,總的來說是cors跨域協議的規范不允許這種操作,在加上瀏覽器和后端的解決庫都不允許不遵循cors跨域協議的規范的請求操作,所以可以使用sa-token前后端分離解決跨域的正確姿勢文章里面的方法,配置一個SimpleCORSFilter,對參數都寫具體,處理預檢測請求返回200狀態碼,或者使用本篇文章的這兩種方式的任意一種都可以解決cors跨域的問題,本文的解決方法是我經過親自打斷點復現跨域請求之后debug出來的解決方法,如果你相信可以按照本文的方法,本地復現跨域請求然后dubug打斷點,看一下是不是corsFilter的CorsUtils.isPreFlightRequest(request)這行代碼的問題,總的來說,這個cors的跨域問題是瀏覽器要背的一個大鍋,簡單請求corsFilter是不會失效的,復雜請求發了預檢測請求(OPTIONS請求),由于瀏覽器的referrer-policy引用者策略會攜帶一個值,后端處理之后會將這個值賦值給請求頭的Orgin屬性上,導致corsFilter的CorsUtils.isPreFlightRequest(request)這行代碼返回true之后就return了,導致后面的一系列的Filter的doFilter沒有執行到,也沒有訪問到后端的接口,而前端瀏覽器頁面還在報跨域的問題,這個問題說實話是真的坑啊。https的方式跨域不行,因為https是監聽443端口,是需要證書的,這個我猜測是要配置證書才可以的,本文洗白了集成sa-token之后會導致corsFilter配置失效的罪名啊,網上千篇一律的文章都沒有本文的這種情況下的解決方法的,應該來說還是首創吧,創作不易,請尊重作者原創,請不要抄襲當做原創,請轉載添加上原創出處,本次分享到此結束,希望我的分享對你有所啟發和幫助,請一鍵三連,么么噠!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43059.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43059.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43059.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

桌面記筆記的軟件:能加密的筆記app

在日常生活和工作中&#xff0c;很多人都有記筆記的習慣。無論是記錄會議要點、學習心得&#xff0c;還是生活中的點滴靈感&#xff0c;筆記都是我們不可或缺的好幫手。然而&#xff0c;傳統的紙筆記錄方式逐漸不能滿足現代人的需求&#xff0c;因為紙質筆記不易保存、查找困難…

STM32 - SPI硬件外設

配合我的上一篇SPI ??????通信 協議-CSDN博客一起理解更佳&#xff0c;本文后看 SPI 是由摩托羅拉(Motorola)公司開發的全雙工同步串行總線&#xff0c;是 MCU 和外圍設備之間進行通信的同步串行端口。主要應用在EEPROM、Flash、RTC、ADC、網絡控制器、MCU、DSP以及數字信…

網上怎么樣可以掙錢,分享幾種可以讓你在家賺錢的兼職項目

當今社會&#xff0c;壓力越來越大&#xff0c;工作、家庭、生活等等&#xff0c;方方面面都需要錢&#xff0c;僅靠一份工作賺錢&#xff0c;已經很難滿足我們的需求。所以很多人都會嘗試做一些副業&#xff0c;兼職來補貼家用。 現在呢&#xff0c;有很多人都想在網上賺錢&am…

微型導軌如何提升數控機床的穩定性?

數控機床是加工設備中常用的機床&#xff0c;精度和穩定性是衡量數控機床性能的重要指標。而微型導軌作為數控機床中重要的傳動元件&#xff0c;數控機床與其具體結構性能是密不可分的&#xff0c;那么微型導軌如何提高數控機床的穩定性呢&#xff1f; 1、微型導軌通過采用先進…

githup開了代理push不上去

你們好&#xff0c;我是金金金。 場景 git push出錯 解決 cmd查看 git config --global http.proxy git config --global https.proxy 如果什么都沒有&#xff0c;代表沒設置全局代理&#xff0c;此時如果你開了代理&#xff0c;則執行如下&#xff0c;設置代理 git con…

關于SQL NOT IN判斷失效的情況記錄

1.準備測試數據 CREATE TABLE tmp_1 (val integer);CREATE TABLE tmp_2 (val integer, val2 integer);INSERT INTO tmp_1 (val) VALUES (1); INSERT INTO tmp_1 (val) VALUES (2); INSERT INTO tmp_2 (val) VALUES (1); INSERT INTO tmp_2 (val, val2) VALUES (NULL,0);2.測…

掃地機器人工作原理

掃地機器人的工作原理主要可以歸納為以下幾個步驟&#xff1a; 一、啟動與建圖 掃地機器人開機后&#xff0c;通常會從充電底座啟動。使用激光導航或視覺導航技術的掃地機器人會開始掃描周圍環境&#xff0c;繪制室內地圖。激光導航的掃地機器人通過激光發射器和接收器測量機…

數據無憂:Ubuntu 系統遷移備份全指南

嘮嘮閑話 最近電腦出現了一些故障&#xff0c;送修期間&#xff0c;不得不在實驗室的臺式機上重裝系統&#xff0c;配環境的過程花費了不少時間。為避免未來處理類似事情時耗費時間&#xff0c;特此整理一些備份策略。 先做以下準備&#xff1a; U盤啟動盤&#xff0c;參考 …

什么是靜態住宅代理?一文看懂它

靜態住宅代理&#xff08;也稱為 ISP 代理&#xff09;是最流行的代理類型之一。它們也是隱藏身份和在線匿名的最佳方式之一。但是您需要了解它們什么&#xff1f;是什么讓它們如此特別&#xff1f;為什么您要使用住宅代理而不是僅僅使用常規代理服務&#xff1f;如果你感興趣&…

exel帶單位求和,統計元素個數

如果exel表格中&#xff0c;如果數據有單位&#xff0c;無法直接用 自動求和 直接求和。如下圖所示&#xff0c;求和結果為0&#xff0c;顯然不是我們想要的。 用下面的公式求和&#xff0c;單位不是“個”的時候記得替換單位。統計范圍不是“C1:C7”也記得換一下啊&#xff01…

華為的服務器創新之路

華為作為全球領先的信息與通信技術解決方案供應商&#xff0c;其在服務器領域的創新方法不僅推動了企業自身的發展&#xff0c;也為整個行業的進步做出了重要貢獻。以下是華為在服務器領域所采取的一些關鍵創新方法&#xff1a; 芯片級的自主創新 華為通過自主研發的“鯤鵬”處…

線程相關概念及操作

【1】線程的概念 1.線程-->進程會得到一個內存地址&#xff0c;進程是資源分配的基本單位線程才是真正進程里處理數據與邏輯的東西進程---》被分配一定的資源線程---》利用進程資源處理數據與邏輯 【2】進程和線程關系&#xff1a; 進程與進程之間是競爭關系&#xff0c;競…

【北京迅為】《i.MX8MM嵌入式Linux開發指南》-第一篇 嵌入式Linux入門篇-

i.MX8MM處理器采用了先進的14LPCFinFET工藝&#xff0c;提供更快的速度和更高的電源效率;四核Cortex-A53&#xff0c;單核Cortex-M4&#xff0c;多達五個內核 &#xff0c;主頻高達1.8GHz&#xff0c;2G DDR4內存、8G EMMC存儲。千兆工業級以太網、MIPI-DSI、USB HOST、WIFI/BT…

BFS:邊權相同的最短路問題

一、邊權相同最短路問題簡介 二、迷宮中離入口最近的出口 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:const int dx[4]{1,-1,0,0};const int dy[4]{0,0,1,-1};int nearestExit(vector<vector<char>>& maze, vector<int>& e…

論文閱讀:Rethinking Interpretability in the Era of Large Language Models

Rethinking Interpretability in the Era of Large Language Models 《Rethinking Interpretability in the Era of Large Language Models》由Chandan Singh、Jeevana Priya Inala、Michel Galley、Rich Caruana和Jianfeng Gao撰寫&#xff0c;探討了在大型語言模型&#xff…

WVP后端項目文件結構

WVP&#xff08;Web Video Platform&#xff09;是一個基于GB28181-2016標準實現的網絡視頻平臺&#xff0c;負責實現核心信令與設備管理后臺部分&#xff0c;支持NAT穿透&#xff0c;支持海康、大華、宇視等品牌的IPC、NVR、DVR接入。支持國標級聯&#xff0c;支持rtsp/rtmp等…

使用C#進行MySQL刪改查操作

使用C#進行MySQL刪改查操作 1.前提準備2.C#中MySQL的向指定數據庫中增加數據3.C#中MySQL的向指定數據庫中修改數據4.C#中MySQL的向指定數據庫中刪除數據 1.前提準備 在MySQL官網上下載C#相關的dll&#xff0c;或者在Nuget包中搜索“MySql.Data”&#xff0c;進行下載。 2.C#中…

js函數擴展內容---多參數,函數屬性,字符串生成函數

1.多參數 在js中&#xff0c;Math.max()方法可以接受任意數量的參數&#xff0c; Math.max(1,2,3,4);//4 Math.max(1,2,3,4,5,6,7,8,9,10)//10 在max方法里面有一個rest參數&#xff0c;它接受了所有參數全部合成到了一個number數組里面&#xff0c; function rest(a,b,...a…

12 - matlab m_map地學繪圖工具基礎函數 - 在地圖上繪制矢量場m_vec函數和繪制風羽圖的m_windbarb函數

12 - matlab m_map地學繪圖工具基礎函數 - 在地圖上繪制矢量場函數m_vec和繪制風羽圖的函數m_windbarb 0. 引言1. 關于m_vec2. 關于m_windbarb3. 總結 0. 引言 本篇介紹下m_map中繪制矢量場的函數&#xff08;m_vec&#xff09;和地圖上繪制風羽圖的函數m_windbarb。 1. 關于m…

【python重復元素判定】

在Python中&#xff0c;判定一個序列&#xff08;如列表、元組等&#xff09;中是否存在重復元素&#xff0c;可以通過多種方法實現。這里列出幾種常用的方法&#xff1a; 1. 使用集合&#xff08;Set&#xff09; 集合是一個無序的、不包含重復元素的數據結構。將序列轉換為…