我正在实现一个应该支持跨域请求的REST API.使用CORS我想实现这一目标.几乎所有的请求都是"不简单",这意味着对于所有非GET请求,浏览器必须发送预检请求.
为了限制预检/ OPTIONS请求的数量,我尝试让浏览器缓存OPTIONS请求.这似乎适用于Firefox和Safari,但不适用于Chrome.我知道Chrome只会将预检请求缓存10分钟,但就我而言,似乎根本没有缓存.
这些是Chrome发送/接收的HTTP请求和响应:
请求:
OPTIONS /api/v1/sessions HTTP/1.1
Host: xxxxxxx
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://localhost:8000/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Run Code Online (Sandbox Code Playgroud)
响应:
HTTP/1.1 200 OK
Date: Sun, 26 Jul 2015 09:33:27 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.9
Cache-Control: private, max-age=1440, pre-check=1440
Access-Control-Allow-Origin: http://localhost:8000
Access-Control-Allow-Methods: GET,POST,PATCH,DELETE
Access-Control-Max-Age: 86400
Access-Control-Allow-Headers: content-type
Content-Length: 0
Keep-Alive: timeout=5, max=100 …Run Code Online (Sandbox Code Playgroud) 我需要在浏览器中使用自定义请求标头发出HTTP GET请求,并在流入时处理结果.Fetch API非常适用于此:
fetch('https://example.com/resource', {
method: 'GET',
headers: {
'X-Brad-Test': 'true'
},
cache: 'no-store',
mode: 'cors'
}).then((res) => {
const reader = res.body.getReader();
// etc.
});
Run Code Online (Sandbox Code Playgroud)
这非常有效.由于存在自定义标头,因此浏览器会使用OPTIONS请求预先处理请求/resource.我已将服务器配置为使用204 No Content以下标头进行响应:
Access-Control-Allow-Headers: X-Requested-With, Range, If-Range, X-Brad-Test
Access-Control-Allow-Origin: *
Run Code Online (Sandbox Code Playgroud)
浏览器对此感到满意,然后发出GET请求,服务器返回200 OK带有数据的内容,浏览器允许我访问响应头和正文.
当存在重定向时,问题就出现了.所述OPTIONS请求与所述成功204 No Content和相同的标头前.浏览器发出正确的GET请求,并在服务器上发送302带有Location:标头的请求.Chrome会引发以下错误:
Fetch API无法加载https://example.com/resource.从' https://example.com/resource ' 重定向到' http:// some-other-origin/resource '已被CORS策略阻止:请求需要预检,不允许遵循跨源重定向.
这是出乎意料的,对我来说似乎毫无意义.我希望浏览器遵循重定向,并为这个新位置做另一个飞行前请求,但它没有这样做.
更奇怪的是,我可以在这个客户端进行黑客攻击.我可以在没有自定义标头的情况下发出HTTP请求,通过查看Response对象找出重定向后的结果,然后使用我的自定义标头在新目标上发出第二个请求.当然,这并不适用于所有情况,我宁愿不依赖这个黑客.我宁愿找到一个合适的方法.
两个问题:
Access-Control-*我可以使用某种标题吗?我无法解决角度4预检请求未通过CORS访问控制检查的问题:"No'Access-Control-Allowed-Origin'".我能够从数据库中成功获取数据,但无法发布/保存数据.我正在使用前端的VS代码访问我的Visual Studio 2015后端.我的Web Api控制器具有以下属性:
[EnableCors(origins: "*", headers: "*", methods: "*")]
[HttpPost]
public async Task<IHttpActionResult> Post([FromBody]Employee employee)
{
_repo.Create(employee);
return Ok();
}
Run Code Online (Sandbox Code Playgroud)
...但是在提出请求时,我收到的错误是:
XMLHttpRequest无法加载http:// localhost:54429/api/createEmployee /.对预检请求的响应未通过访问控制检查:请求的资源上不存在"Access-Control-Allow-Origin"标头.因此不允许来源' http:// localhost:4200 '访问
在我的vs代码中,我的服务看起来像这样:
postEmployeeForm(employee: Employee): Observable<any>{
let body = JSON.stringify(employee);
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let options = new RequestOptions({ headers: headers });
console.log('posting employee ' , employee);
return this.http.post("http://localhost:54429/api/employees/", body, options)
.map(this.extractData)
.catch(this.handleError)
}
Run Code Online (Sandbox Code Playgroud)
405从帖子中删除正文和选项后的响应.
不确定我错过了什么.
网络配置
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 …Run Code Online (Sandbox Code Playgroud) cors asp.net-web-api preflight angular2-forms angular2-observables
我想知道浏览器如何处理包含Vary: Origin和Access-Control-Max-Age标头的CORS 预检响应。
本声明来自https://www.w3.org/TR/cors/
希望使自己能够与多个源共享但不以“*”统一响应的资源必须在实践中动态生成 Access-Control-Allow-Origin 标头以响应它们希望允许的每个请求。因此,此类资源的作者应发送 Vary: Origin HTTP 标头或提供其他适当的控制指令以防止缓存此类响应,如果跨源重用可能会不准确
从这个声明我明白Vary: Origin会告诉浏览器阻止预检响应的缓存(如果 allow-origin: * not used)
Access-Control-Max-Age将告诉浏览器将缓存预检响应一段时间。
问题:
如果预检响应中存在两个标头,它是否有效?
如果响应包含这两个标头,浏览器如何处理预检响应?
谢谢!
我在 ASP.net Core 2(Windows 身份验证)上有一个 API,在 angular 上有一个前端。我进行了 cors 配置以从 SPA 角度查询我的后端,但由于预检而被 IIS 服务器拒绝,因为他没有身份信息而被阻止。
错误信息 :
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://XXXXXX' is therefore not allowed access. The response had HTTP status code 401.
Run Code Online (Sandbox Code Playgroud)
代码侧正面:
//MY HEADER
private headers = new Headers({
'Content-Type': 'application/json',
'Access-Control-Allow-Credentials':'true',
'Access-Control-Allow-Origin':'true'
});
//REQUEST
let options = new RequestOptions({headers:this.headers, withCredentials:true});
return this.http.get(this.tasksUrl,options).map(res=>res.json());
Run Code Online (Sandbox Code Playgroud)
代码背面:(Startup.cs)
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddCors(options =>
{ …Run Code Online (Sandbox Code Playgroud) javascript windows-authentication cors asp.net-web-api preflight
我正在使用 CFT 为我的 API 创建环境。我已经添加了 CORS 选项。我注意到当我进行测试时AWS console for OPTIONS我收到了200回复。但是,当我执行相同操作时,CURL or PostMan我收到500内部服务器错误。在审查了与之相关的问题后。我已将集成响应修改为 CONVERT_TO_TEXT。但这也没有解决问题。
我注意到日志中存在有线行为。以下是来自 AWS 控制台的请求的日志片段:
Sat Apr 13 15:06:26 UTC 2019 : Method request headers: { Access-Control-Request-Method= POST, Content-Type= application/json}
Sat Apr 13 15:06:26 UTC 2019 : Method request body before transformations:
Sat Apr 13 15:06:26 UTC 2019 : Method response body after transformations:
Sat Apr 13 15:06:26 UTC 2019 : Method response headers: {X-Requested-With=*, Access-Control-Allow-Headers=Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-requested-with, Access-Control-Allow-Origin=*, Access-Control-Allow-Methods=POST,OPTIONS, Content-Type=application/json}
Sat Apr …Run Code Online (Sandbox Code Playgroud) 我在Preflight request for request with keepalive specified is currently not supported使用keepalive启用的 fetch api 调用 POST 请求时遇到错误。任何帮助,将不胜感激 。我在beforeunload事件中调用这个 api 。
API 请求
fetch(uri, {
method: 'POST',
headers: {
'Content-type': options.headers.get('content-type'),
'Authorization': options.headers.get('authorization')
},
body: JSON.stringify(interactionBody),
keepalive: true
}).catch((e) => {
console.log(e);
});
Run Code Online (Sandbox Code Playgroud) 由于我不明白的原因,Safari 无法(间歇性但持续地)连接到我们 QA 基础设施上的 Rails 应用程序(静态前端和 API 后端)。(我将就此写另一个问题。)
目前,让我感到困惑的一件事是,Safari(一般来说)似乎从未显示其他浏览器(Chrome 和 Firefox)在其 XHR 网络列表(在开发人员工具中)中明确显示的选项(预检)请求。我只看到 POST 和 GET 请求等,从未看到任何 OPTION 请求。
Safari 是否制作了它们,只是不展示它们?Safari 似乎对我们的 DEMO 和 PROD 基础设施(其设置略有不同)表现良好,因此我很想假设这只是他们的开发人员工具的差异,而不是表明出现了问题。
safari cors http-options-method preflight safari-web-inspector
我想我对 CORS 非常了解,但是当涉及到预检请求时,我仍然对浏览器的行为感到有点困惑。
假设浏览器发出此预检请求:
OPTIONS http://myserver.local:7000/api/order/4 HTTP/1.1
Host: myserver.local:7000
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-my-custom-header
Origin: http://localhost:5000
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
Run Code Online (Sandbox Code Playgroud)
我的 API 返回:
HTTP/1.1 204 No Content
Date: Wed, 09 Mar 2022 12:52:50 GMT
Server: Kestrel
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT,DELETE
Access-Control-Allow-Origin: http://localhost:5000
Vary: Origin
Run Code Online (Sandbox Code Playgroud)
请注意,服务器允许在预检请求的响应中使用PUT和方法,但不允许,这是实际 CORS 请求的方法。DELETEPOST
由于实际请求的方法与标头中列出的方法不匹配,浏览器是否应该阻止此请求Access-Control-Allow-Methods?或者服务器用20x状态代码响应浏览器接受预检然后发送实际请求就足够了吗?
我的假设是,如果请求的方法不匹配,浏览器会比较允许方法并阻止请求......我错过了什么吗?
我在预检请求方面遇到了一个奇怪的问题。
这是在我们的应用程序中执行某些操作后,它在 Chrome(以及其他基于 chromium 的浏览器)中的外观:

许多预检请求被标记为红色失败 (net::ERR_FAILED)。
但最终,每个请求都会有一个预检请求,该请求成功并返回204,并且应用程序可以正常工作。所以看起来浏览器尝试了几次,最终没问题,但是日志中的许多项目都是红色的......
在 Firefox 中,预检请求甚至不可见,看起来一切都很好:

在 API 的 Program.cs 中,我们有这样的代码,它应该使它始终可以使用 AllowAnyMethod() 工作,它应该接受任何 OPTIONS 请求:
var allowedOrigins = app.Configuration.GetSection("appSettings") != null
? app.Configuration.GetSection("appSettings").GetSection("AllowedCorsOrigins").GetChildren().Select(x => x.Value).ToArray()
: Array.Empty<string>();
Trace.WriteLine("allowed origins:" + string.Join(',', allowedOrigins));
app.UseCors(x => x
.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.WithExposedHeaders("Content-Disposition"));
Run Code Online (Sandbox Code Playgroud)
我还尝试使用中间件来解决这个问题:/sf/answers/2953983091/ 但它的工作原理是一样的。
Chrome 发出如此多失败的预检请求的原因可能是什么?正常吗?是 Chrome 错误、网络错误还是 API 错误?
谢谢您的回答。我可以添加更多信息,只需告诉我您需要了解的内容即可。
顺便说一句,我在控制台日志中没有任何 CORS 错误。