我的环境:
- 后端(localhost)用.net web api 2编写
启用包“Microsoft.AspNet.WebApi.Cors” - 前端(localhost)使用 vue-js-2 和 webpack-simple
用于http请求的vue资源
我遇到了一些无法解决的 CORS 问题:
使用 GET 动词启动“简单请求”是可行的,但是当使用 POST 动词时,我收到 CORS 错误,说:
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's CORS reference并注意到我的 POST 请求确实首先作为预检请求发送,并带有 OPTIONS 动词和 Access-Control-Request-Method: POST
header 。
在我的 WebApiConfig 文件中,我有:
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请求代码如下:
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);
});
}
以及 Controller 中的POST函数:
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 请求 header 定义为授权的“text/plain”。使用 Fiddler 我找到了传出请求,但它没有文本/纯标题。 现在,我什至不确定我的错误是否与后端配置有关或与前端请求发送方法有关。 有人遇到过类似的事情吗? (对所有代码感到抱歉,我希望尽可能包罗万象但最少)
最佳答案
Web Api 2 不响应 OPTIONS 请求。您可以为其添加 Handler。这是我一次解决它的方法。在某处创建一个 IHttpModule。这是我的:
namespace AAWebSmartHouse.WebApi.Infrastructure.Modules
{
using System.Web;
public class OPTIONSVerbHandlerModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, args) =>
{
var app = (HttpApplication)sender;
if (app.Request.HttpMethod == "OPTIONS")
{
app.Response.StatusCode = 200;
app.Response.AddHeader("Access-Control-Allow-Headers", "content-type,accept,authorization");
app.Response.AddHeader("Access-Control-Allow-Origin", "*");
app.Response.AddHeader("Access-Control-Allow-Credentials", "true");
app.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
app.Response.AddHeader("Content-Type", "application/json");
app.Response.AddHeader("Accept", "application/json");
app.Response.End();
}
};
}
public void Dispose()
{
}
}
}
并将其添加到 Web.config 中:
<modules>
<!-- ... -->
<add name="OPTIONSVerbHandlerModule" type="AAWebSmartHouse.WebApi.Infrastructure.Modules.OPTIONSVerbHandlerModule" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<!-- ... -->
</handlers>
如果它仍然没有响应 Controller 中某些方法的 OPTIONS 请求,我发现我已经添加了这样的 AcceptVerbs 属性:
// GET api/Account/UserInfo
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UserInfo")]
[AcceptVerbs("OPTIONS", "GET")]
public UserInfoViewModel GetUserInfo()
{
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
return new UserInfoViewModel
{
Email = User.Identity.GetUserName(),
HasRegistered = externalLogin == null,
LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
};
}
关于.net - vue 和 dotnet 的 cors 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53665751/