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

為什么瀏覽器會進行OPTIONS預檢請求深入講解

 更新時間:2026年04月15日 09:50:13   作者:微笑1234  
options請求是用于請求服務器對于某些接口等資源的支持情況的,包括各種請求方法、頭部的支持情況,僅作查詢使用,這篇文章主要介紹了為什么瀏覽器會進行OPTIONS預檢請求的相關資料,需要的朋友可以參考下

一、什么是跨域請求

1.1 同源策略(Same-Origin Policy)

同源策略是瀏覽器的一種安全機制,用于限制一個源(Origin)的文檔或腳本如何與另一個源的資源進行交互。

什么是"源"(Origin)

源由三部分組成:協議(Protocol)+ 域名(Domain)+ 端口(Port)

https://www.example.com:443/api/users
└─┬─┘   └──────┬──────┘ └┬┘
協議        域名        端口

同源判斷規(guī)則

只有當兩個 URL 的協議、域名、端口完全相同時,才被認為是同源。

當前頁面 URL目標 URL是否同源原因
https://www.example.com/page1https://www.example.com/page2? 同源協議、域名、端口都相同
https://www.example.com/page1http://www.example.com/page2? 跨域協議不同(https vs http)
https://www.example.com/page1https://api.example.com/page2? 跨域域名不同(www vs api)
https://www.example.com/page1https://www.example.com:8080/page2? 跨域端口不同(443 vs 8080)
https://www.example.com/page1https://www.example.org/page2? 跨域域名不同(.com vs .org)

1.2 什么是跨域請求

跨域請求是指從一個源向另一個不同源的服務器發(fā)起的 HTTP 請求。

典型的跨域場景

場景 1:前后端分離架構

前端頁面:https://www.example.com
后端 API:https://api.example.com
→ 跨域(域名不同)

場景 2:本地開發(fā)環(huán)境

前端開發(fā)服務器:http://localhost:3000
后端開發(fā)服務器:http://localhost:8080
→ 跨域(端口不同)

場景 3:CDN 資源加載

網站頁面:https://www.example.com
CDN 資源:https://cdn.example.com
→ 跨域(域名不同)

場景 4:第三方 API 調用

網站頁面:https://www.mysite.com
第三方 API:https://api.thirdparty.com
→ 跨域(域名完全不同)

1.3 同源策略限制的內容

瀏覽器的同源策略會限制以下跨域行為:

1. Ajax/Fetch 請求

// 從 https://www.example.com 發(fā)起請求
fetch('https://api.example.com/users')  // ? 被同源策略阻止
  .then(response => response.json())
  .catch(error => console.error('跨域錯誤:', error));

2. Cookie、LocalStorage、IndexedDB 訪問

// 無法讀取其他域的 Cookie
document.cookie  // 只能訪問當前域的 Cookie

3. DOM 訪問

// 無法訪問 iframe 中不同源頁面的 DOM
const iframe = document.getElementById('myIframe');
iframe.contentWindow.document  // ? 跨域訪問被阻止

1.4 不受同源策略限制的內容

以下資源加載不受同源策略限制:

1. 圖片、CSS、JavaScript 文件

<!-- ? 允許跨域加載 -->
<img src="https://cdn.example.com/image.jpg">
<link rel="stylesheet"  rel="external nofollow" >
<script src="https://cdn.example.com/script.js"></script>

2. 表單提交

<!-- ? 允許跨域提交 -->
<form action="https://api.example.com/submit" method="POST">
  <input type="text" name="username">
  <button type="submit">提交</button>
</form>

3. 頁面跳轉

// ? 允許跨域跳轉
window.location.;

1.5 跨域解決方案

方案 1:CORS(跨域資源共享)- 推薦

服務器通過設置響應頭允許跨域請求:

Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

方案 2:JSONP(僅支持 GET 請求)

利用 <script> 標簽不受同源策略限制的特性:

// 前端
function handleResponse(data) {
  console.log(data);
}
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);

方案 3:代理服務器

通過同源的代理服務器轉發(fā)請求:

瀏覽器 → 同源代理服務器 → 目標服務器
1. 瀏覽器(https://www.example.com)
   ↓ 發(fā)起請求到同源代理
2. 代理服務器(https://www.example.com/proxy)
   ↓ 轉發(fā)請求到目標服務器
3. 目標服務器(https://api.thirdparty.com)
   ↓ 返回數據給代理
4. 代理服務器
   ↓ 返回數據給瀏覽器
5. 瀏覽器接收數據(同源,沒有跨域問題)

實際例子(Node.js Express):

// 前端代碼(運行在 http://localhost:3000)
fetch('/proxy/api/users')  // 請求同源的代理接口
  .then(response => response.json())
  .then(data => console.log(data));
// 后端代理服務器代碼(也運行在 http://localhost:3000)
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/proxy/api/users', async (req, res) => {
  // 代理服務器去請求真正的目標服務器
  const response = await axios.get('https://api.thirdparty.com/users');
  res.json(response.data);  // 返回給前端
});
app.listen(3000);

方案 4:Nginx 反向代理

瀏覽器訪問:https://www.example.com/api/users
              ↓
Nginx 接收請求(https://www.example.com)
              ↓
Nginx 根據 location 規(guī)則匹配 /api/
              ↓
Nginx 轉發(fā)到:https://api.example.com/users
              ↓
后端服務器返回數據
              ↓
Nginx 返回給瀏覽

實際配置例子

server {
    listen 80;
    server_name www.example.com;
    # 前端靜態(tài)資源
    location / {
        root /var/www/html;
        index index.html;
    }
    # API 請求代理到后端服務器
    location /api/ {
        # 將 /api/users 轉發(fā)到 https://api.example.com/users
        proxy_pass https://api.example.com/;
        # 傳遞原始請求信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

1.6 為什么需要同源策略

安全保護

  1. 防止 CSRF 攻擊:惡意網站無法讀取其他網站的 Cookie
  2. 保護用戶隱私:防止惡意腳本竊取用戶數據
  3. 隔離不同站點:確保網站之間的數據隔離

示例:沒有同源策略的危險場景

// 假設沒有同源策略
// 用戶訪問惡意網站 evil.com
fetch('https://bank.com/api/account')  // 能讀取銀行賬戶信息
  .then(response => response.json())
  .then(data => {
    // 惡意網站竊取用戶銀行數據
    sendToHacker(data);
  });

二、什么是 OPTIONS 預檢請求

OPTIONS 請求是瀏覽器在發(fā)送跨域請求前自動發(fā)起的一種"預檢請求"(Preflight Request),用于檢查服務器是否允許實際的跨域請求。

1.1 觸發(fā)條件

瀏覽器會在以下情況下自動發(fā)起 OPTIONS 預檢請求:

簡單請求 vs 非簡單請求

簡單請求(不會觸發(fā) OPTIONS)需要同時滿足:

  • 請求方法為:GET、HEADPOST
  • HTTP 頭部僅包含:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type(僅限 application/x-www-form-urlencodedmultipart/form-data、text/plain

非簡單請求(會觸發(fā) OPTIONS)包括:

  • 使用 PUT、DELETEPATCH 等方法
  • 發(fā)送 application/json 類型的數據
  • 自定義 HTTP 頭部(如 Authorization、X-Custom-Header
  • 攜帶 Cookie 或認證信息

跨域請求 vs 同源請求

  • 情況 1:同源 + 簡單請求 → ? 不發(fā)送 OPTIONS 示例:
// 頁面:http://localhost:9087/index.html
// API: http://localhost:9087/api/users
fetch('http://localhost:9087/api/users', {
    method: 'GET'
});

結果: 直接發(fā)送 GET 請求,沒有 OPTIONS 原因: 同源請求不需要 CORS 檢查

  • 情況 2:同源 + 非簡單請求 → ? 不發(fā)送 OPTIONS 示例:
// 頁面:http://localhost:9087/index.html
// API: http://localhost:9087/api/users/123
fetch('http://localhost:9087/api/users/123', {
    method: 'PUT',  // 非簡單方法
    headers: {
        'Content-Type': 'application/json',  // 非簡單 Content-Type
        'Authorization': 'Bearer token123'   // 自定義頭部
    },
    body: JSON.stringify({ name: '張三' })
});

結果: 直接發(fā)送 PUT 請求,沒有 OPTIONS 原因: 同源請求不需要 CORS 檢查(即使是非簡單請求)

  • 情況 3:跨域 + 簡單請求 → ? 不發(fā)送 OPTIONS 示例:
// 頁面:http://localhost:63342/index.html
// API: http://localhost:9087/api/users
fetch('http://localhost:9087/api/users', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: 'name=張三'
});

結果: 直接發(fā)送 POST 請求,沒有 OPTIONS 原因: 雖然跨域,但是簡單請求,不需要預檢

  • 情況 4:跨域 + 非簡單請求 → ? 發(fā)送 OPTIONS 示例:
// 頁面:http://localhost:63342/index.html
// API: http://localhost:9087/api/users/123
fetch('http://localhost:9087/api/users/123', {
    method: 'PUT',  // 非簡單方法
    headers: {
        'Content-Type': 'application/json'  // 非簡單 Content-Type
    },
    body: JSON.stringify({ name: '張三' })
});

結果: 先發(fā)送 OPTIONS 預檢,預檢通過后再發(fā)送 PUT 請求順序: OPTIONS /api/users/123 ← 預檢請求 PUT /api/users/123 ← 實際請求 原因: 跨域 + 非簡單請求,需要預檢確認服務器是否允許

二、為什么瀏覽器要發(fā)起 OPTIONS 請求

2.1 安全機制:同源策略(Same-Origin Policy)

瀏覽器的同源策略是一種安全機制,限制了不同源之間的資源訪問。OPTIONS 預檢請求是 CORS(跨域資源共享)機制的核心組成部分。

2.2 OPTIONS 請求的作用

  1. 安全驗證:在發(fā)送實際請求前,先詢問服務器是否允許跨域訪問
  2. 權限確認:檢查服務器是否允許特定的 HTTP 方法和頭部
  3. 避免副作用:防止非簡單請求直接修改服務器數據
  4. 性能優(yōu)化:通過緩存預檢結果,減少后續(xù)請求的預檢次數

2.3 工作流程

客戶端                                服務器
  |                                    |
  |  1. OPTIONS 預檢請求                 |
  |  (詢問是否允許跨域)                   |
  | ---------------------------------> |
  |                                    |
  |  2. 返回 CORS 響應頭                 |
  |  (告知允許的方法、頭部等)              |
  | <--------------------------------- |
  |                                    |
  |  3. 發(fā)送實際請求                     |
  |  (POST/PUT/DELETE 等)              |
  | ---------------------------------> |
  |                                    |
  |  4. 返回業(yè)務數據                     |
  | <--------------------------------- |

三、OPTIONS 請求示例

3.1 預檢請求示例

OPTIONS /api/users/123 HTTP/1.1                     # OPTIONS 方法:預檢請求;/api/users/123:請求路徑(包含用戶ID 123);HTTP/1.1:使用的 HTTP 協議版本
Accept: */*                                         # 客戶端接受任何類型的響應內容
Accept-Encoding: gzip, deflate, br, zstd            # 客戶端支持的壓縮算法
Accept-Language: zh-CN,zh;q=0.9                     # 客戶端首選中文語言
Access-Control-Request-Headers: content-type        #【預檢關鍵】實際請求將攜帶的自定義請求頭(Content-Type)
Access-Control-Request-Method: PUT                  #【預檢關鍵】實際請求將使用的 HTTP 方法(PUT)
Connection: keep-alive                              # 保持 TCP 連接以便復用
Host: localhost:9087                                # 目標服務器地址和端口
Origin: http://localhost:63342                      #【預檢關鍵】發(fā)起請求的源地址(前端頁面地址)
Referer: http://localhost:63342/                    # 請求的來源頁面 URL
Sec-Fetch-Dest: empty                               # 請求的目標類型(empty 表示 CORS 預檢)
Sec-Fetch-Mode: cors                                #【預檢關鍵】請求模式為 CORS 跨域請求
Sec-Fetch-Site: same-site                           # 請求的站點關系(same-site 表示同站但不同端口)
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36  # 瀏覽器標識信息

3.2 服務器響應示例

HTTP/1.1 200                                         # HTTP 
Vary: Origin                                         # 告訴緩存服務器:響應內容會根據請求的 Origin 頭而變化
Vary: Access-Control-Request-Method                  # 告訴緩存服務器:響應內容會根據請求的方法而變化
Vary: Access-Control-Request-Headers                 # 告訴緩存服務器:響應內容會根據請求的頭部而變化
Access-Control-Allow-Origin: http://localhost:63342  # 【核心】允許的源地址,必須與請求的 Origin 完全匹配
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS # 【核心】允許的 HTTP 方法列表,告訴瀏覽器這些方法可以跨域使用
Access-Control-Allow-Headers: content-type           # 【核心】允許的請求頭,響應預檢請求中的 Access-Control-Request-Headers
Access-Control-Expose-Headers: Content-Disposition, X-File-Size, X-Download-Token, X-Total-Count, X-Page-Size, X-Current-Page, X-Total-Pages, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
                                                    # 暴露給前端 JavaScript 的自定義響應頭列表
                                                    # 前端可通過 response.headers.get('X-Total-Count') 等方式讀取這些頭
Access-Control-Max-Age: 0                           # 預檢結果的緩存時間(秒),0 表示不緩存,每次都需要發(fā)送預檢請求
Content-Length: 0                                   # 響應體長度為 0(預檢請求無響應體)
Date: Mon, 09 Feb 2026 02:09:02 GMT                 # 服務器響應時間
Keep-Alive: timeout=60                              # TCP 連接保持時間為 60 秒
Connection: keep-alive                              # 保持 TCP 連接,避免頻繁建立連接

四、Gateway 層面的處理方案

4.1 核心配置要點

1. 允許 OPTIONS 方法

確保 Gateway 不會攔截或拒絕 OPTIONS 請求。

2. 返回正確的 CORS 響應頭

必須包含以下關鍵響應頭:

響應頭說明示例值
Access-Control-Allow-Origin允許的源https://www.example.com*
Access-Control-Allow-Methods允許的 HTTP 方法GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers允許的請求頭Content-Type, Authorization,或*
Access-Control-Max-Age預檢結果緩存時間(秒)86400(24小時)
Access-Control-Allow-Credentials是否允許攜帶憑證true

Access-Control-Allow-Credentials 是 CORS 中用于控制是否允許跨域請求攜帶憑證(Cookie、HTTP 認證信息等)的響應頭,一般情況下會設置成*。

3. 快速響應 OPTIONS 請求

OPTIONS 請求不需要轉發(fā)到后端服務,應在 Gateway 層直接返回 200 響應。

4.2 Spring Cloud Gateway 配置方案

方案一:全局 CORS 配置(推薦)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
/**
 * 全局 CORS 跨域配置
 * 用于處理瀏覽器的 OPTIONS 預檢請求
 */
@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 允許的源(生產環(huán)境應指定具體域名)
        config.addAllowedOriginPattern("*");
        // 允許的 HTTP 方法
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("OPTIONS");
        // 允許的請求頭
        config.addAllowedHeader("*");
        // 是否允許攜帶憑證(Cookie)
        config.setAllowCredentials(true);
        // 預檢請求的緩存時間(秒)
        config.setMaxAge(86400L);
        // 暴露給前端的響應頭
        config.addExposedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

方案二:application.yml 配置

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            # 允許的源
            allowed-origin-patterns: "*"
            # 允許的方法
            allowed-methods:
              - GET
              - POST
              - PUT
              - DELETE
              - OPTIONS
            # 允許的請求頭
            allowed-headers: "*"
            # 是否允許攜帶憑證
            allow-credentials: true
            # 預檢請求緩存時間(秒)
            max-age: 86400

方案三:自定義 GlobalFilter(高級場景)

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
 * 全局 CORS 過濾器
 * 優(yōu)先級最高,確保 OPTIONS 請求被正確處理
 */
@Component
public class CorsGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = response.getHeaders();
        // 獲取請求源
        String origin = request.getHeaders().getOrigin();
        // 設置 CORS 響應頭
        if (origin != null) {
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
        }
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "86400");
        // 如果是 OPTIONS 請求,直接返回 200
        if (request.getMethod() == HttpMethod.OPTIONS) {
            response.setStatusCode(HttpStatus.OK);
            return Mono.empty();
        }
        // 繼續(xù)執(zhí)行后續(xù)過濾器
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        // 設置最高優(yōu)先級
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

4.3 Nginx Gateway 配置方案

server {
    listen 80;
    server_name api.example.com;
    # 處理 OPTIONS 預檢請求
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '$http_origin' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Max-Age' 86400 always;
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
    # 為所有響應添加 CORS 頭
    add_header 'Access-Control-Allow-Origin' '$http_origin' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    location /api/ {
        proxy_pass http://backend-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

4.4 配置建議

生產環(huán)境安全配置

// ? 不推薦:允許所有源
config.addAllowedOrigin("*");
// ? 推薦:指定具體域名
config.addAllowedOrigin("https://www.example.com");
config.addAllowedOrigin("https://admin.example.com");
// ? 推薦:使用 Pattern 支持多個子域名
config.addAllowedOriginPattern("https://*.example.com");

性能優(yōu)化配置

// 設置較長的緩存時間,減少預檢請求頻率
config.setMaxAge(86400L); // 24 小時
// 僅暴露必要的響應頭
config.addExposedHeader("Content-Disposition");
config.addExposedHeader("X-Total-Count");

五、瀏覽器這么做的意義

5.1 安全保障

  1. 防止 CSRF 攻擊:通過預檢機制,確保只有授權的源才能發(fā)起跨域請求
  2. 保護用戶數據:避免惡意網站未經授權訪問用戶的敏感數據
  3. 服務器主動控制:讓服務器決定哪些跨域請求是安全的

5.2 兼容性保障

  1. 向后兼容:保護不支持 CORS 的舊服務器不被意外訪問
  2. 漸進增強:允許現代 Web 應用安全地進行跨域通信

5.3 性能優(yōu)化

  1. 緩存機制:通過 Access-Control-Max-Age 緩存預檢結果
  2. 減少請求:緩存期內的相同請求不再發(fā)起預檢
  3. 快速失敗:在預檢階段就能發(fā)現跨域問題,避免浪費資源

六、常見問題與解決方案

6.1 問題:每次請求都發(fā)起 OPTIONS

原因

  • 未設置 Access-Control-Max-Age 響應頭
  • 緩存時間設置過短
  • 請求頭或方法發(fā)生變化

解決方案

// 設置較長的緩存時間
config.setMaxAge(86400L); // 24 小時

6.2 問題:OPTIONS 請求返回 403 或 404

原因

  • Gateway 未正確處理 OPTIONS 請求
  • 路由配置不匹配 OPTIONS 方法

解決方案

  • 確保 CORS 過濾器優(yōu)先級最高
  • 在 Gateway 層直接返回 200,不轉發(fā)到后端

6.3 問題:攜帶 Cookie 的請求失敗

原因

  • 未設置 Access-Control-Allow-Credentials: true
  • 使用了 Access-Control-Allow-Origin: *(與 Credentials 沖突)

解決方案

config.setAllowCredentials(true);
config.addAllowedOriginPattern("https://www.example.com"); // 不能用 *

6.4 問題:設置 Cookie 的接口跨域失敗

現象

  • 前端調用登錄接口,使用了 withCredentials: true
  • 后端設置了 config.setAllowCredentials(false) 或未設置
  • 瀏覽器報錯:CORS policy blocked

總結

  • withCredentials: trueAccess-Control-Allow-Credentials: true 必須同時存在
  • 這個配置不僅影響攜帶 Cookie,也影響接收 Cookie(Set-Cookie)
  • 設置 Cookie 的登錄接口也需要這個配置

6.5 問題:自定義請求頭被拒絕

原因

  • 未在 Access-Control-Allow-Headers 中聲明

解決方案

config.addAllowedHeader("Authorization");
config.addAllowedHeader("X-Custom-Header");
// 或者允許所有頭部(開發(fā)環(huán)境)
config.addAllowedHeader("*");

七、最佳實踐總結

7.1 開發(fā)環(huán)境配置

// 寬松配置,方便開發(fā)調試
config.addAllowedOriginPattern("*");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
config.setMaxAge(3600L);

7.2 生產環(huán)境配置

// 嚴格配置,確保安全
config.addAllowedOriginPattern("https://*.example.com");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
config.addAllowedHeader("Content-Type");
config.addAllowedHeader("Authorization");
config.setAllowCredentials(true);
config.setMaxAge(86400L);

7.3 監(jiān)控與日志

@Slf4j
@Component
public class CorsLoggingFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        if (request.getMethod() == HttpMethod.OPTIONS) {
            log.info("OPTIONS 預檢請求: {} from {}", 
                request.getURI(), 
                request.getHeaders().getOrigin());
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 1;
    }
}

八、總結

OPTIONS 預檢請求是瀏覽器的安全機制,雖然會增加一次額外的請求,但通過合理配置:

  1. 在 Gateway 層統(tǒng)一處理 CORS,避免每個微服務重復配置
  2. 設置合理的緩存時間,減少預檢請求頻率
  3. 生產環(huán)境嚴格控制允許的源,確保安全性
  4. 開發(fā)環(huán)境寬松配置,提高開發(fā)效率

這樣既能保證安全性,又能優(yōu)化性能,是現代 Web 應用的標準做法。

九、參考資料

到此這篇關于為什么瀏覽器會進行OPTIONS預檢請求的文章就介紹到這了,更多相關瀏覽器OPTIONS預檢請求內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MyBatis-Plus 之selectMaps、selectObjs、selectCount、selectOne的使用

    MyBatis-Plus 之selectMaps、selectObjs、selectCount、selectO

    本文主要介紹了MyBatis-Plus 之selectMaps、selectObjs、selectCount、selectOne的使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 如何完成spring的最小化XML配置

    如何完成spring的最小化XML配置

    這篇文章主要介紹了如何完成spring的最小化XML配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下
    2019-06-06
  • Java 反射機制知識詳細介紹及總結

    Java 反射機制知識詳細介紹及總結

    反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調用對象的方法的功能稱為java語言的反射機制
    2017-01-01
  • 淺談JAVA中輸入輸出流實例詳解

    淺談JAVA中輸入輸出流實例詳解

    Java中的流分為兩種,一種是字節(jié)流,另一種是字符流。這篇文章主要介紹了JAVA中輸入輸出流的相關資料,需要的朋友可以參考下
    2016-07-07
  • spring boot攔截器實現IP黑名單實例代碼

    spring boot攔截器實現IP黑名單實例代碼

    本篇文章主要介紹了spring boot攔截器實現IP黑名單實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • spring boot定時器實現定時同步數據的操作步驟

    spring boot定時器實現定時同步數據的操作步驟

    在Java中,@Scheduled注解是用于指定定時任務的執(zhí)行規(guī)則的,這篇文章給大家介紹spring boot定時器實現定時同步數據的操作步驟,感興趣的朋友一起看看吧
    2023-12-12
  • java音頻播放示例分享(java如何播放音頻)

    java音頻播放示例分享(java如何播放音頻)

    java如何播放音頻?下面的代碼就介紹了java音頻播放示例,需要的朋友可以參考下
    2014-04-04
  • Java讀取DBF文件(GBK編碼)的方法

    Java讀取DBF文件(GBK編碼)的方法

    在Java開發(fā)中,有時需要讀取DBF(dBase文件)格式的數據文件,而這些文件通常采用GBK(簡體中文)編碼,本文將介紹如何使用Java讀取采用GBK編碼的DBF文件,需要的朋友可以參考下
    2024-11-11
  • 使用Java實現將一個正整數分解質因數

    使用Java實現將一個正整數分解質因數

    這篇文章主要介紹了如何使用Java語言實現將一個正整數分解為質因數的功能,首先,我們定義了一個正整數并調用一個方法來輸出其質因數分解結果,需要的朋友可以參考下
    2026-01-01
  • Java線程池execute()和submit()的對比詳解

    Java線程池execute()和submit()的對比詳解

    這段文章詳細對比了execute()和submit()在Java線程池中的核心區(qū)別,包括返回值、異常處理及支持的任務類型,并提供了實戰(zhàn)代碼示例,關鍵詞:execute()、submit()、線程池提交任務,需要的朋友可以參考下
    2026-06-06

最新評論

芒康县| 墨玉县| 图木舒克市| 绩溪县| 肇源县| 安福县| 嘉义市| 武威市| 威信县| 涿州市| 德兴市| 徐水县| 定安县| 资溪县| 正安县| 彝良县| 松桃| 辰溪县| 林口县| 平南县| 盖州市| 周至县| 夏邑县| 灵丘县| 阆中市| 长治市| 阳曲县| 和林格尔县| 健康| 威海市| 镇雄县| 洞头县| 犍为县| 旺苍县| 綦江县| 临潭县| 方山县| 嵊泗县| 绵阳市| 马尔康县| 茶陵县|