最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot CORS 配置方法允許跨域請求的最佳實(shí)踐方案

 更新時(shí)間:2024年11月20日 11:37:22   作者:baby bear 竟陵  
跨域請求在現(xiàn)代Web開發(fā)中非常重要,特別是在涉及多個(gè)前端和后端服務(wù)時(shí),本文詳細(xì)介紹了跨域請求的背景、重要性以及如何解決跨域問題,通過SpringBoot框架的CORS配置,可以有效地處理跨域請求,確保數(shù)據(jù)傳輸?shù)陌踩院陀脩趔w驗(yàn),感興趣的朋友跟隨小編一起看看吧

跨域請求的背景和重要性

在現(xiàn)代 Web 開發(fā)中,跨域請求是一個(gè)常見且重要的概念。隨著互聯(lián)網(wǎng)應(yīng)用的日益復(fù)雜,尤其是在涉及多個(gè)前端和后端服務(wù)的情況下,跨域問題經(jīng)常會(huì)對應(yīng)用的功能和用戶體驗(yàn)造成影響。

背景

開發(fā)項(xiàng)目時(shí),遇到一個(gè)需求,當(dāng)時(shí)項(xiàng)目配套的線下商鋪已由物業(yè)交付給我司運(yùn)營,運(yùn)營團(tuán)隊(duì)需要招商引資,經(jīng)過公司考慮決定開發(fā)一個(gè)公眾號交給運(yùn)營團(tuán)隊(duì),以便客戶能夠在線選擇商鋪。公眾號內(nèi)嵌一個(gè)H5頁面,做到用戶點(diǎn)擊平面圖中單元格(每一個(gè)商鋪號就是一個(gè)單元格)優(yōu)先鎖定商鋪,由于商鋪分布在多個(gè)區(qū)域,UI繪圖也需要時(shí)間,再加需求緊迫,項(xiàng)目必須在三天內(nèi)上線。前端團(tuán)隊(duì)采用了 Canvas 技術(shù),讓用戶能夠直觀地選擇商鋪單元格,并填寫提交個(gè)人資料。開發(fā)過程中,前后端進(jìn)行了接口聯(lián)調(diào),在測試環(huán)境中沒有明顯的問題。然而,當(dāng)項(xiàng)目部署到微信公眾號后,出現(xiàn)了跨域請求問題,直接是空白頁面。

當(dāng)時(shí),前端因?yàn)榕渲么淼倪M(jìn)度緩慢,跨域配置的解決方案轉(zhuǎn)到了后端。這一問題突顯了跨域請求在 Web 開發(fā)中的重要性,特別是在需要與多個(gè)服務(wù)進(jìn)行交互時(shí)。

跨域請求的重要性

  • 安全性:瀏覽器的同源政策旨在保護(hù)用戶,防止惡意網(wǎng)站竊取信息??缬蛘埱笮枰?jīng)過嚴(yán)格的檢查和配置,以確保數(shù)據(jù)傳輸?shù)陌踩浴?/li>
  • 用戶體驗(yàn):跨域請求的限制可能會(huì)導(dǎo)致用戶在操作過程中遇到障礙,影響應(yīng)用的流暢性和可用性。在我們的項(xiàng)目中,如果不及時(shí)解決跨域問題,將會(huì)直接影響客戶體驗(yàn)和業(yè)務(wù)進(jìn)展。
  • 業(yè)務(wù)需求:在某些情況下,業(yè)務(wù)需求可能需要不同來源的資源交互。例如,在我們開發(fā)的微信公眾號中,需要與后端服務(wù)進(jìn)行數(shù)據(jù)交互,以完成用戶的選擇和定金繳納等操作。
  • 快速迭代:隨著項(xiàng)目的推進(jìn),及時(shí)處理跨域問題是確保項(xiàng)目快速上線的重要環(huán)節(jié)。在短時(shí)間內(nèi)解決跨域配置,能夠?yàn)楹罄m(xù)的功能擴(kuò)展和業(yè)務(wù)發(fā)展打下良好的基礎(chǔ)。

什么是跨域 

跨域是指在 Web 應(yīng)用中,由于瀏覽器的同源政策(Same-Origin Policy),不同源的網(wǎng)頁之間進(jìn)行交互時(shí)所遇到的限制。源的定義包括三個(gè)部分:協(xié)議(如 httphttps)、域名(如 example.com)和端口(如 80443)。只有當(dāng)這三者都相同的時(shí)候,兩個(gè) URL 被認(rèn)為是同源的。

為什么有同源政策?

通俗來說,瀏覽器廠商開發(fā)出來的瀏覽器都是有做安全限制的,當(dāng)你打開某個(gè)網(wǎng)站時(shí),瀏覽器就已經(jīng)將請求標(biāo)頭中的origin屬性改成了當(dāng)前網(wǎng)站的域名。例如我訪問bilibili,會(huì)是這樣的一個(gè)origin,你在當(dāng)前頁面中做以下幾種操作,均會(huì)出現(xiàn)跨域:

跨域的情形

1,http://www.bilibili.com(假設(shè)存在)

2,https://www.bilibili.com:8086(假設(shè)存在)

3,http://admin.www.bilibili.com(假設(shè)存在)

跨域原因解釋

情況1跨域的原因是scheme(標(biāo)識特定協(xié)議或資源類型的字符串)變了

情況2 跨域的原因是port(端口號)變了

情況3跨域的原因是host(域名,admin.www.bilibili.com是域名)變了

如何證明上述情況就是跨域?

跨不跨域框架說了算,來看看Springboot框架是如何認(rèn)定為跨域的,先附上截圖,然后給源碼解釋

處理請求相關(guān)的參數(shù),并通過比較來判斷是否跨域的源碼

package org.springframework.web.cors;
public abstract class CorsUtils {
    public CorsUtils() {
    }
//方法名就直接體現(xiàn)了方法的作用,判斷是否是跨域請求
public static boolean isCorsRequest(HttpServletRequest request) {
        String origin = request.getHeader("Origin");
        if (origin == null) {
            return false;
        } else {
            UriComponents originUrl = UriComponentsBuilder.fromOriginHeader(origin).build();
            String scheme = request.getScheme();
            String host = request.getServerName();
            int port = request.getServerPort();
//上面的代碼是從請求體中獲取協(xié)議,域名,端口的value值,拿到這些值就是為了和Origin作比較
//通過截圖也能看到Origin包含了scheme,host,port,他們分別是https,www.bilibili.com,443
            return !ObjectUtils.nullSafeEquals(scheme, originUrl.getScheme())
 || !ObjectUtils.nullSafeEquals(host, originUrl.getHost())
 || getPort(scheme, port) != getPort(originUrl.getScheme(), originUrl.getPort());
        }
    }
}

源碼中不難看出來,在經(jīng)過一番處理之后,會(huì)通過客戶端傳遞的Origin中的信息和接口服務(wù)資源做協(xié)議,端口,域名的比對,只要有一處不一樣那就是跨域,框架會(huì)告知瀏覽器跨域,具體的比對過程并不難,我已經(jīng)貼出來了包名和類名,鼓勵(lì)朋友們自己動(dòng)手。

為什么是這樣,而不是那樣

既然服務(wù)器有處理請求,為什么你在瀏覽器上看不到響應(yīng)回來的HTTP狀態(tài)碼,服務(wù)器應(yīng)該要給客戶端返回個(gè)狀態(tài)碼,取而代之的卻是顯示:此請求沒有發(fā)起程序請求或者類似的其他提示,這都要?dú)w功于預(yù)檢請求,也是瀏覽器廠商默認(rèn)遵循的一個(gè)標(biāo)準(zhǔn)規(guī)范,屬于 CORS(跨源資源共享)機(jī)制的一部分。

跨域提示截圖

或者

預(yù)檢請求

預(yù)檢請求(Preflight Request)是 CORS(跨源資源共享)機(jī)制中的一個(gè)重要概念,用于在發(fā)送復(fù)雜的跨域請求之前,先向服務(wù)器發(fā)送一個(gè) HTTP OPTIONS 請求,以確認(rèn)服務(wù)器是否允許實(shí)際的請求。預(yù)檢請求的目的是為了增強(qiáng)安全性,確保客戶端在發(fā)送敏感數(shù)據(jù)時(shí)得到服務(wù)器的許可。

何時(shí)觸發(fā)預(yù)檢請求

預(yù)檢請求通常在以下情況下觸發(fā):

1.復(fù)雜請求

  • 當(dāng)使用的 HTTP 方法不是簡單請求中的 GET 或 POST(如 PUT、DELETE)。
  • 當(dāng)請求中包含自定義頭部(例如,X-Custom-Header)。
  • 當(dāng) Content-Type 的值不是簡單請求允許的類型(如 application/x-www-form-urlencoded、multipart/form-datatext/plain)。

2.服務(wù)器端的 CORS 配置

  • 只有在服務(wù)器配置了 CORS,并明確允許來自特定源的請求時(shí),預(yù)檢請求才會(huì)返回成功。

預(yù)檢請求關(guān)服務(wù)器什么事情 

完全不瞎說,有沒有預(yù)檢請求,依舊是springboot框架說了算,先附上原圖,在附上部分源碼

當(dāng)我從知乎頁面上請求我本機(jī)的服務(wù)接口時(shí)

服務(wù)器處理預(yù)檢請求

首先服務(wù)器確實(shí)收到了該次請求,截圖如下:

57255edf057d457f96a065319e298236.png

處理預(yù)檢請求的截圖:

1600abebf4584464ab5b8cbda32ffcb2.png

OPTIONS請求就是預(yù)檢請求的請求方式,這里解釋不了為什么,只能回答這就是規(guī)范

處理預(yù)檢請求的源碼:

 public static boolean isPreFlightRequest(HttpServletRequest request) {
        //先判斷是不是OPTIONS請求,若是,則表示是預(yù)檢請求
        return HttpMethod.OPTIONS.matches(request.getMethod())
        //預(yù)檢請求時(shí),http請求頭一定要給Origin
         && request.getHeader("Origin") != null 
        //預(yù)檢請求時(shí),會(huì)給定名為Access-Control-Request-Method的請求頭
         && request.getHeader("Access-Control-Request-Method") != null;
    }

服務(wù)器如何處理跨域呢,允許還是不允許? 

允許還是不允許,完全看程序員如何設(shè)置跨域規(guī)則,跨域策略,不做深入講解,但是教你如何避開雷區(qū),先看看核心邏輯的截圖

服務(wù)器會(huì)判斷當(dāng)前是否是預(yù)檢請求,如果是,則會(huì)調(diào)用一個(gè)處理內(nèi)部請求的方法,如圖

關(guān)鍵點(diǎn):allowOrigin為什么為null,checkOrigin方法到底做了什么比較

知識點(diǎn)回顧

問題到這里很清晰了,當(dāng)程序執(zhí)行到ObjectUtils.isEmpty(this.allowedOrigins)或者this.allowedOrigins.contains("*"),if語句的條件不成立了,因?yàn)閠his.allowedOrigins并不包含客戶端的域名,也就是例子中的https://www.bilbili.com或者h(yuǎn)ttps://www.zhihu.com,我們要處理的正是allowedOrigins,

private List<String> allowedOrigins;

他是以數(shù)組的形式被持有的,有很多個(gè)API可以給這個(gè)數(shù)組初始化值,在我的代碼中,只展示一種,因?yàn)槲覀円獙W(xué)的不是API,而是發(fā)現(xiàn)問題,拆分問題,解決問題的心法,API什么的不重要。

以上介紹了什么是跨域,跨域的情形,以及預(yù)檢請求作為web瀏覽器的規(guī)范,以及服務(wù)器如何處理預(yù)檢請求,瀏覽器對于未通過的預(yù)檢請求會(huì)以什么形式展示給用戶,接下來告訴大家如何解決這種小小的問題~

springboot解決跨域的方式非常之多,但是從最底層解決,往往能學(xué)到更多指定問題之外的知識

SpringBoot允許跨域的后端代碼

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        //config.setAllowCredentials(true); // 允許發(fā)送憑據(jù),雷區(qū)
        config.addAllowedOrigin("*"); //允許任意域名跨域訪問接口
        config.addAllowedHeader("*"); // 允許所有頭部信息
        config.addAllowedMethod("*"); // 允許所有請求方法
        source.registerCorsConfiguration("/**", config); // 應(yīng)用于所有路徑
        return new CorsFilter(source);
    }
}

這段配置足已解決前端跨域問題,之前說的雷區(qū)就是允許發(fā)送憑據(jù)的代碼和config.addAllowedOrigin("*");不可以一起使用,否則會(huì)報(bào)錯(cuò)。到這里,一切OK,前端跨域的問題已經(jīng)解決~

給大家一段便捷的JS代碼用來測試跨域問題,JS代碼不做解釋,相信看懂不成問題

模擬跨域的JS代碼

var xhr = new XMLHttpRequest();
xhr.open('post', 'http://localhost:8081/admin/captcha/v1/generateCaptcha');
xhr.setRequestHeader('Content-Type', 'application/json'); // 設(shè)置請求頭
xhr.setRequestHeader('authracation', 'abcdefghijklmnopqrstuvwxyz'); // 設(shè)置請求頭
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
};
xhr.send('{}');

這段js代碼,按F12,在瀏覽器的控制臺(tái)中直接執(zhí)行,支持IE和Google瀏覽器,親測有效,需要根據(jù)實(shí)際的請求進(jìn)行微調(diào),不要在你自己的WEB項(xiàng)目或者API文檔頁面打開,否則無法達(dá)到測試跨域的效果,具體原因,我相信你理解了上面的知識點(diǎn)之后應(yīng)該能明白。解決問題的代碼很少,但是知識點(diǎn)并不少,留心處處皆學(xué)問哈

到此這篇關(guān)于Spring Boot CORS 配置詳解:允許跨域請求的最佳實(shí)踐的文章就介紹到這了,更多相關(guān)Spring Boot CORS 跨域請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot+Vue簡單前后端分離項(xiàng)目的增刪改查方式

    SpringBoot+Vue簡單前后端分離項(xiàng)目的增刪改查方式

    文章主要介紹了使用SpringBoot進(jìn)行前后端開發(fā)的過程,包括SpringBoot項(xiàng)目的搭建、配置、后端業(yè)務(wù)開發(fā)、前端頁面搭建等步驟,并詳細(xì)闡述了數(shù)據(jù)增刪改查的實(shí)現(xiàn)方法
    2026-04-04
  • 基于springboot與axios的整合問題

    基于springboot與axios的整合問題

    這篇文章主要介紹了springboot與axios的整合問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 基于mybatis中數(shù)組傳遞注意事項(xiàng)

    基于mybatis中數(shù)組傳遞注意事項(xiàng)

    這篇文章主要介紹了mybatis中數(shù)組傳遞注意事項(xiàng),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java自定義日期轉(zhuǎn)化類示例

    java自定義日期轉(zhuǎn)化類示例

    這篇文章主要介紹了java自定義日期轉(zhuǎn)化類示例,需要的朋友可以參考下
    2014-05-05
  • SpringBoot接收接口入?yún)⒌姆绞叫〗Y(jié)

    SpringBoot接收接口入?yún)⒌姆绞叫〗Y(jié)

    這篇文章主要給大家介紹了SpringBoot接收接口入?yún)⒌膸追N方式,我們從調(diào)用方的視角去看待這個(gè)問題,對調(diào)用方來說,它在調(diào)用接口時(shí)有好幾種傳參方式,下面,將會(huì)依次對這幾種參數(shù)方式進(jìn)行講解和代碼示例,需要的朋友可以參考下
    2024-01-01
  • Spring創(chuàng)建Bean的過程Debug的詳細(xì)流程

    Spring創(chuàng)建Bean的過程Debug的詳細(xì)流程

    這篇文章主要介紹了Spring創(chuàng)建Bean的過程Debug的流程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 解決因jdk版本引起的TypeNotPresentExceptionProxy異常

    解決因jdk版本引起的TypeNotPresentExceptionProxy異常

    這篇文章介紹了解決因jdk版本引起的TypeNotPresentExceptionProxy異常的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • idea設(shè)置@Author文件頭注釋的實(shí)現(xiàn)步驟

    idea設(shè)置@Author文件頭注釋的實(shí)現(xiàn)步驟

    本文主要介紹了idea設(shè)置@Author文件頭注釋的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • java selenium 操作彈出窗口示例代碼

    java selenium 操作彈出窗口示例代碼

    本文主要介紹java selenium 操作彈出窗口,這里實(shí)例講解操作彈出窗口詳細(xì)流程,并附示例代碼,有需要的小伙伴可以參考下
    2016-08-08
  • SpringBoot整合WebService服務(wù)的實(shí)現(xiàn)代碼

    SpringBoot整合WebService服務(wù)的實(shí)現(xiàn)代碼

    WebService是一個(gè)SOA(面向服務(wù)的編程)的架構(gòu),它是不依賴于語言,不依賴于平臺(tái),可以實(shí)現(xiàn)不同的語言間的相互調(diào)用,通過Internet進(jìn)行基于Http協(xié)議的網(wǎng)絡(luò)應(yīng)用間的交互,這篇文章主要介紹了SpringBoot整合WebService服務(wù)的實(shí)例代碼,需要的朋友可以參考下
    2022-02-02

最新評論

肥乡县| 蒙阴县| 西乌珠穆沁旗| 云霄县| 盐池县| 中牟县| 房产| 沙湾县| 信宜市| 和政县| 潮安县| 班戈县| 阳泉市| 江源县| 恩平市| 株洲市| 蓬溪县| 定结县| 丁青县| 香格里拉县| 伊春市| 固镇县| 青州市| 宁国市| 长乐市| 阿巴嘎旗| 松原市| 怀柔区| 区。| 焉耆| 丹棱县| 略阳县| 改则县| 新田县| 南丰县| 苏尼特右旗| 东阳市| 西丰县| 上犹县| 杭锦后旗| 阜宁县|