为什么要发送OPTIONS请求,我可以禁用它吗?

部署运行你感兴趣的模型镜像

本文翻译自:Why is an OPTIONS request sent and can I disable it?

I am building a web API. 我正在构建一个Web API。 I found whenever I use Chrome to POST, GET to my API, there is always an OPTIONS request sent before the real request, which is quite annoying. 我发现每当我使用Chrome进行POST,GET到我的API时,总是在真实请求之前发送一个OPTIONS请求,这很烦人。 Currently I get the server to ignore any OPTIONS requests. 目前,我让服务器忽略任何OPTIONS请求。 Now my questions is what's good to send an OPTIONS request to double the server's load? 现在,我的问题是,发送一个OPTIONS请求以使服务器的负载增加一倍有什么好处? Is there any way to completely stop the browser from sending OPTIONS requests? 有什么方法可以完全阻止浏览器发送OPTIONS请求?


#1楼

参考:https://stackoom.com/question/21gPd/为什么要发送OPTIONS请求-我可以禁用它吗


#2楼

edit 2018-09-13 : added some precisions about this pre-flight request and how to avoid it at the end of this reponse. 编辑2018-09-13 :在此预检请求以及在此响应结束时如何避免它方面增加了一些精度。

OPTIONS requests are what we call pre-flight requests in Cross-origin resource sharing (CORS) . OPTIONS请求是Cross-origin resource sharing (CORS) pre-flight请求。

They are necessary when you're making requests across different origins in specific situations. 当您在特定情况下跨不同来源发出请求时,它们是必需的。

This pre-flight request is made by some browsers as a safety measure to ensure that the request being done is trusted by the server. 某些浏览器会发出此飞行前请求,作为一种安全措施,以确保服务器信任正在执行的请求。 Meaning the server understands that the method, origin and headers being sent on the request are safe to act upon. 意味着服务器了解请求上发送的方法,源和标头是安全的。

Your server should not ignore but handle these requests whenever you're attempting to do cross origin requests. 每当您尝试进行跨源请求时,服务器都不应忽略,而应处理这些请求。

A good resource can be found here http://enable-cors.org/ 一个很好的资源可以在这里找到http://enable-cors.org/

A way to handle these to get comfortable is to ensure that for any path with OPTIONS method the server sends a response with this header 处理这些问题的一种方法是确保对于使用OPTIONS方法的任何路径,服务器均使用此标头发送响应

Access-Control-Allow-Origin: *

This will tell the browser that the server is willing to answer requests from any origin. 这将告诉浏览器服务器愿意回答任何来源的请求。

For more information on how to add CORS support to your server see the following flowchart 有关如何向服务器添加CORS支持的更多信息,请参见以下流程图

http://www.html5rocks.com/static/images/cors_server_flowchart.png http://www.html5rocks.com/static/images/cors_server_flowchart.png

CORS流程图


edit 2018-09-13 编辑2018-09-13

CORS OPTIONS request is triggered only in somes cases, as explained in MDN docs : 仅在某些情况下会触发CORS OPTIONS请求,如MDN docs中所述

Some requests don't trigger a CORS preflight. 有些请求不会触发CORS预检。 Those are called “simple requests” in this article, though the Fetch spec (which defines CORS) doesn't use that term. 尽管Fetch规范(定义了CORS)未使用该术语,但在本文中将其称为“简单请求”。 A request that doesn't trigger a CORS preflight—a so-called “simple request”—is one that meets all the following conditions: 不会触发CORS预检的请求(所谓的“简单请求”)是满足以下所有条件的请求:

The only allowed methods are: 唯一允许的方法是:

  • GET 得到
  • HEAD
  • POST 开机自检

Apart from the headers set automatically by the user agent (for example, Connection, User-Agent, or any of the other headers with names defined in the Fetch spec as a “forbidden header name”), the only headers which are allowed to be manually set are those which the Fetch spec defines as being a “CORS-safelisted request-header”, which are: 除了由用户代理自动设置的标头(例如,Connection,User-Agent或在Fetch规范中定义为“禁止标头名”的任何其他标头)外,仅允许将标头手动设置的是Fetch规范定义为“ CORS安全列出的请求标头”的设置,它们是:

  • Accept 接受
  • Accept-Language 接受语言
  • Content-Language 内容语言
  • Content-Type (but note the additional requirements below) 内容类型(但请注意以下其他要求)
  • DPR DPR
  • Downlink 下行链接
  • Save-Data 保存数据
  • Viewport-Width 视口宽度
  • Width 宽度

The only allowed values for the Content-Type header are: Content-Type标头的唯一允许值为:

  • application/x-www-form-urlencoded 应用程序/ x-www-form-urlencoded
  • multipart/form-data 多部分/表单数据
  • text/plain 文字/纯文字

No event listeners are registered on any XMLHttpRequestUpload object used in the request; 没有在请求中使用的任何XMLHttpRequestUpload对象上注册事件侦听器; these are accessed using the XMLHttpRequest.upload property. 这些可以使用XMLHttpRequest.upload属性进行访问。

No ReadableStream object is used in the request. 请求中未使用ReadableStream对象。


#3楼

您不能,但是可以避免使用JSONP的CORS。


#4楼

Yes it's possible to avoid options request. 是的,可以避免选择要求。 Options request is a preflight request when you send (post) any data to another domain. 当您将任何数据发送(发布)到另一个域时,选项请求是预检请求。 It's a browser security issue. 这是浏览器的安全问题。 But we can use another technology: iframe transport layer. 但是我们可以使用另一种技术:iframe传输层。 I strongly recommend you forget about any CORS configuration and use readymade solution and it will work anywhere. 我强烈建议您忘记任何CORS配置并使用现成的解决方案,它可以在任何地方使用。

Take a look here: https://github.com/jpillora/xdomain 在这里看看: https : //github.com/jpillora/xdomain

And working example: http://jpillora.com/xdomain/ 工作示例: http : //jpillora.com/xdomain/


#5楼

Please refer this answer on the actual need for pre-flighted OPTIONS request: CORS - What is the motivation behind introducing preflight requests? 请根据实际的预检选项请求参阅此答案: CORS-引入预检请求的动机是什么?

To disable the OPTIONS request, below conditions must be satisfied for ajax request: 要禁用OPTIONS请求,必须满足ajax请求的以下条件:

  1. Request does not set custom HTTP headers like 'application/xml' or 'application/json' etc 请求未设置自定义HTTP标头,例如“ application / xml”或“ application / json”等
  2. The request method has to be one of GET, HEAD or POST. request方法必须是GET,HEAD或POST之一。 If POST, content type should be one of application/x-www-form-urlencoded , multipart/form-data , or text/plain 如果是POST,则内容类型应为application/x-www-form-urlencodedmultipart/form-datatext/plain

Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 参考: https : //developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS


#6楼

As mentioned in previous posts already, OPTIONS requests are there for a reason. 如前几篇文章所述, OPTIONS请求在那里是有原因的。 If you have an issue with large response times from your server (eg overseas connection) you can also have your browser cache the preflight requests. 如果您对服务器的响应时间过长(例如,海外连接)有疑问,还可以让浏览器缓存预检请求。

Have your server reply with the Access-Control-Max-Age header and for requests that go to the same endpoint the preflight request will have been cached and not occur anymore. 让您的服务器用Access-Control-Max-Age标头答复,对于转到相同端点的请求,预检请求将被缓存并且不再发生。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think> 我们面对的问题是:在配置了域名允许跨域的情况下,OPTIONS预检请求成功(通常返回200或204),但后续的GET或POST请求却返回403错误。这种情况通常与跨域配置本身无关,而是由服务器端的安全机制拦截了实际请求。 根据引用内容及常见原因分析,以下是可能的原因及解决方案: ### 1. **CSRF保护拦截非GET请求(Spring Security场景)** - **问题本质**:Spring Security默认启用CSRF保护,会拦截所有**非GET**请求(如POST/PUT/DELETE)。虽然GET请求通常不受影响,但如果安全配置过于严格也可能拦截GET请求。 - **解决方案**: - **开发环境**:禁用CSRF ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); // 禁用CSRF保护 } } ``` - **生产环境**:保留CSRF但配置例外(推荐仅对API路径禁用) ```java http.csrf() .ignoringAntMatchers("/api/**"); // 忽略API路径的CSRF检查 ``` ### 2. **安全权限配置拦截请求** - **问题本质**:Spring Security的URL权限配置未放行业务接口。 - **典型表现**:OPTIONS请求通过(因预检请求通常是匿名访问),但实际业务请求需要认证。 - **解决方案**:显式配置接口访问权限 ```java http.authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行所有OPTIONS请求 .antMatchers("/api/public/**").permitAll() // 放行公共接口 .antMatchers("/api/**").authenticated() // 需认证的接口 .anyRequest().denyAll(); // 其他请求拒绝 ``` ### 3. **拦截器未正确处理认证** - **问题本质**:自定义拦截器放行了OPTIONS请求,但未正确处理实际请求的认证(如JWT校验失败)。 - **解决方案**:确保拦截器对非OPTIONS请求执行认证逻辑 ```java public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 放行OPTIONS预检请求 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { return true; } // 检查实际请求的认证信息(如Token) String token = request.getHeader("Authorization"); if (!validateToken(token)) { response.setStatus(401); // 返回401未授权 return false; } return true; } } ``` ### 4. **CORS配置与安全配置冲突** - **问题本质**:CORS配置正确,但安全配置覆盖了CORS响应头(如Spring Security的默认行为)。 - **解决方案**:在Spring Security中显式启用CORS ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .cors() // 启用Spring Security的CORS支持 .and() ... // 其他配置 } // 配置CORS源(需定义CorsConfigurationSource Bean) @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("https://console.163yun.com")); config.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } } ``` ### 5. **Nginx/Tomcat等Web服务器配置问题** - **问题本质**:Web服务器(如Nginx)仅处理了OPTIONS请求,但未转发实际请求到应用服务器(如引用[3][4])。 - **解决方案**:确保Nginx配置同时支持OPTIONS和实际请求 ```nginx location / { # 处理预检请求 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; return 204; } # 转发实际请求到后端 proxy_pass http://backend-server; } ``` ### 诊断流程图 ```mermaid graph TD A[GET/POST返回403] --> B{是否是非GET请求?} B -->|是| C[检查CSRF配置] B -->|否| D[检查URL权限配置] C --> E[禁用CSRF或配置例外] D --> F[确认接口已放行] E --> G[问题解决] F --> G G --> H[结束] ``` > **关键验证步骤**: > 1. 使用Postman直接发送GET/POST请求(不带Origin头),确认是否仍返回403。 > - 如果是 → **安全配置问题**(非跨域原因) > - 如果否 → **跨域配置问题** > 2. 检查浏览器控制台错误信息: > - 若提示 `CORS error` → 跨域头未生效 > - 若提示 `403 Forbidden` → 服务器安全拦截 通过以上步骤,90%的OPTIONS成功但实际请求403的问题可定位到具体原因[^1][^3][^4]。 §§相关问题§§ 1. 如何区分CORS错误和CSRF导致的403错误? 2. Spring Security中如何为REST API禁用CSRF保护? 3. 为什么OPTIONS请求需要特殊处理? 4. 微服务架构中如何统一管理跨域配置? </think>在配置了域名允许跨域的情况下,OPTIONS预检请求成功但GET/POST请求返回403错误,主要涉及以下核心原因和解决方案: --- ### 一、根本原因分析 1. **CSRF保护拦截非GET请求** Spring Security默认启用CSRF保护,会拦截所有**非GET请求**(如POST/PUT/DELETE)。即使跨域配置正确,CSRF仍会拒绝这些请求[^1][^3]。 2. **安全权限配置未放行实际接口** OPTIONS预检请求通常被放行(因其不携带业务数据),但实际业务接口(GET/POST)可能被安全策略拦截: ```java http.authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行OPTIONS .antMatchers("/api/data").authenticated() // GET/POST请求需认证 ``` 3. **拦截器或过滤器未放行业务请求** 自定义拦截器可能放行了OPTIONS请求,但未正确处理后续业务请求的认证: ```java public boolean preHandle(HttpServletRequest request) { if ("OPTIONS".equals(request.getMethod())) return true; // 放行预检 // 但对GET/POST请求执行了拦截 if (request.getSession().getAttribute("user") == null) { response.setStatus(403); return false; } } ``` 4. **证书配置冲突** 启用`allowCredentials(true)`(携带Cookie)时,`allowedOrigins("*")`会导致冲突: ```java // 错误配置(冲突) .allowedOrigins("*") .allowCredentials(true); // 正确配置(需指定具体域名) .allowedOrigins("https://your-domain.com") .allowCredentials(true); ``` --- ### 二、解决方案 #### 1. 针对CSRF保护 ```java @Configuration @EnableWebSecurity public class SecurityConfig { protected void configure(HttpSecurity http) { http .csrf().disable() // 方案1:禁用CSRF(开发环境) // 或 .csrf().ignoringAntMatchers("/api/**"); // 方案2:仅对API路径禁用 } } ``` #### 2. 配置安全策略放行业务接口 ```java http.authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行所有OPTIONS .antMatchers(HttpMethod.GET, "/public/**").permitAll() // 放行GET请求 .antMatchers(HttpMethod.POST, "/submit").hasRole("USER") // 按需配置 .anyRequest().authenticated(); ``` #### 3. 修复拦截器逻辑 ```java public boolean preHandle(HttpServletRequest request) { // 放行所有OPTIONS请求 if ("OPTIONS".equals(request.getMethod())) { return true; } // 处理业务请求的认证 if (!checkAuth(request)) { response.sendError(401, "Unauthorized"); return false; } return true; } ``` #### 4. 统一CORS配置(避免冲突) ```java @Bean CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("https://your-domain.com")); // 非* config.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS")); config.setAllowCredentials(true); // 允许Cookie UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); } ``` --- ### 三、诊断流程图 ```mermaid graph TD A[GET/POST返回403] --> B{请求类型} B -->|GET| C[检查安全权限配置] B -->|POST/PUT/DELETE| D[检查CSRF配置] C --> E[确认URL是否被 permitAll] D --> F[是否禁用CSRF?] E -->|否| G[添加权限放行] F -->|否| H[禁用CSRF或配置例外] G --> I[问题解决] H --> I ``` > **关键验证**: > 用Postman直接发送GET/POST请求(不带`Origin`头),若仍返回403 → **非跨域问题**,需检查安全配置; > 若正常返回 → **跨域配置问题**,检查CORS响应头是否缺失。 --- ### 四、Nginx层补充配置 若问题发生在网关层,参考引用[3][4]配置: ```nginx location / { # 放行预检请求 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' 'https://your-domain.com'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type'; return 204; } # 处理业务请求 add_header 'Access-Control-Allow-Origin' 'https://your-domain.com'; add_header 'Access-Control-Allow-Credentials' 'true'; proxy_pass http://backend; } ``` 通过以上步骤,可解决90%的OPTIONS成功但业务请求403的问题[^1][^3][^4]。 --- ### 相关问题 1. 如何区分CORS错误和CSRF导致的403错误? 2. Spring Security中如何为REST API禁用CSRF保护? 3. 为什么OPTIONS请求需要特殊处理? 4. 微服务架构中如何统一管理跨域配置
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值