问题描述
我的环境:
my environments:
- 用.net Web API 2编写的
- 后端(localhost)
已启用软件包"Microsoft.AspNet.WebApi.Cors" 带有webpack-simple的vue-js-2的 - 前端(localhost)
http请求的vue资源
- backend (localhost) written in .net web api 2
enabled package "Microsoft.AspNet.WebApi.Cors" - frontend (localhost) with vue-js-2 with webpack-simple
vue-resource for http requests
我遇到了一些无法解决的CORS问题:
使用GET动词启动简单请求"是可行的,但是使用POST动词时会出现CORS错误,提示:
I am experiencing some CORS issues which I cannot solve:
Launching "simple requests" with GET verb works, but when using POST verb I get CORS error, saying:
Access to XMLHttpRequest at 'http://localhost:59837/api/Employees' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我已阅读 mozilla的CORS参考信息并注意到实际上我的POST请求实际上是先作为预检请求发送的,带有OPTIONS动词和 Access-Control-Request-Method:POST
标头.
I've read mozilla's CORS reference and noticed that indeed my POST request is sent as a preflight request first, with OPTIONS verb and Access-Control-Request-Method: POST
header.
:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// Web API enable CORS
System.Web.Http.Cors.EnableCorsAttribute cors = new System.Web.Http.Cors.EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
}
,我的POST请求代码如下:
and my POST request code is as follows:
testPOST(){
const credentials = { username: '1', password: '11'};
this.$http.post('http://localhost:59837/api/Employees', {params: {id: '2'}, body: credentials, method: 'POST', headers: {'Content-Type': 'text/plain'}})
.then(function (response){
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
以及控制器中的POST功能:
and the POST function in the controller:
public async Task<HttpResponseMessage> PostEmployees(Credentials creds)
{
Employees emp = await db.Employees.FindAsync(Int32.Parse(creds.username));
if (emp.password.Equals(creds.password))
{
emp.password = "";
return Request.CreateResponse(HttpStatusCode.OK, emp);
}
else
return Request.CreateResponse(HttpStatusCode.Unauthorized, "Username or password are incorrect");
}
我的想法是,也许我需要为授权的文本/纯文本"定义POST请求标头.使用Fiddler,我发现了传出的请求,但是它没有text/plain标头.现在,我什至不确定我的错误是否与后端配置或前端请求发送方法有关.有人遇到过类似的事情吗?(对不起所有代码,我想尽可能少地包含所有内容)
My thinking was that perhaps I need to define the POST request headers to the authorized "text/plain". Using Fiddler I found the outgoing request but it didn't have the text/plain header..Right now, I am not even sure if my error is related to the backend configuration or to the frontend request sending method.Any one encountered anything similar? (sorry for all the code, I wanted to be as encompassing yet minimal as possible)
推荐答案
解决方案
我认为问题实际上与前端和后端有关.
微软的Web API 2教程似乎没有提到它缺乏对某些客户端作为飞行前"请求生成的OPTIONS标头的支持.另外,我在Vue-Resource中使用的参数也引起了一些问题.
后端:
1.我更改了默认行为,导致服务器丢弃 Global.asax.cs 中带有OPTIONS标头的所有请求,谢谢 Obelixx :
Solution
I think the problem was actually both front- and back-end related.
Microsoft's Web API 2's tutorial doesn't seem to mention its lack of support for the OPTIONS header that is generated by some clients as "pre-flight" request.In addition, the parameters I was using in Vue-Resource's also caused some problems.
Back-end:
1. I changed the default behavior that caused the server to drop all requests with OPTIONS header in Global.asax.cs, thanks Obelixx:
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
//Response.Flush();
Response.StatusCode = 200;
Response.AddHeader("Access-Control-Allow-Headers", "content-type,accept,authorization");
Response.AddHeader("Access-Control-Allow-Origin", "*");
Response.AddHeader("Access-Control-Allow-Credentials", "true");
Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE");
Response.AddHeader("Content-Type", "application/json");
Response.AddHeader("Accept", "application/json");
Response.End();
}
我真的不确定这是最好的解决方案,我确信.net程序员完全有理由要删除所有OPTIONS请求,这需要更深入地研究,因此请谨慎使用.
2.如此处所示,我还在控制器类中添加了OPTIONS动作:
I'm really not sure that's the best solution, I'm sure there's a perfectly good reason why .net programmers thought all OPTIONS requests should be dropped, this needs deeper digging into it, so use with caution.
2. as can be seen here, I also added an OPTIONS actions in my controller class:
// OPTIONS: allow pre-flight
public HttpResponseMessage Options()
{
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}
前端:
1. vue-resource的API表示对POST请求具有以下签名:
front-end:
1. vue-resource's API says has this signature for POST request:
post(url, [body], [config])
但还说您可以将主体包含在配置参数中.
好吧,这并不能满足要求.所以代替这个:
but also says you can include the body inside the config paramter.
well, that didn't work for met. so instead of this:
this.$http.post('http://localhost:59837/api/Employees',
{params: {id: '2'}, body: credentials, method: 'POST', headers: {'Content-Type': 'text/plain'}})
我这样做了:
this.$http.post('http://localhost:59837/api/Employees', credentials,
{headers: {'Content-Type': 'application/json'}})
请注意我是如何取出正文的:凭据出来,只是将凭据用作单独的参数.
2.我还将"Content-Type"标头从 text/plain 更改为 application/json (微软表示,应将 text/plain 类型阻止预检,但这只会导致json格式化程序无法解析凭据).
----
因此,这就是目前的解决方案,就像我说的是同时具有前端和后端相关的修复程序一样,我不确定是否真的有那么多错误或只是我在许多地方修补的未发现的错误.
我希望这对其他人有帮助.
notice how i took the body: credentials out and just used credentials as a separate argument.
2. I also changed the 'Content-Type' header from text/plain to application/json (microsoft says that text/plain types should prevent the pre-flight, but that only caused my json formatter to fail parsing credentials).
----
So that's the solution for now, like I said I had both front- and back-end related fixes, I'm not sure if there were really so many bugs or just an undiscovered one that I patched in many places.
I hope this helps other people.
这篇关于vue和dotnet的cors问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!