我有一个来自VS 2013的Web API 2项目,使用Nuget的5.0.0.0 DLL(最近已经加载)。
我还创建了一个限制起源的自定义CorsPolicy。这似乎工作正常,我按照这里的指示:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
我和Fiddler注意到的是,虽然OPTIONS动词被400 Bad Request正确阻止,但POST动词直接传递给控制器,然后然后调用CorsPolicy ,但到那时,Post动作已经成功,并且客户获得了200 OK的回报。
我期待POST被400 Bad Request以及OPTION动词阻止。如果我正确理解CORS TR,它应该被阻止。
以下是来自单个POST的Web API的诊断跟踪,其中我使用Fiddler将Origin标头设置为http://localhose
。请记住 - 完全相同的情况正确地被OPTION动词阻止。
w3wp.exe Information: 0 : Request, Method=POST, Url=http://myhost/myvdir/api/v1/MyCntrllr/MyAction, Message='http://myhost/myvdir/api/v1/MyCntrllr/MyAction'
w3wp.exe Information: 0 : Message='MyCntrllr', Operation=DefaultHttpControllerSelector.SelectController
w3wp.exe Information: 0 : Message='MyNamespace.Controllers.MyCntrllrController', Operation=DefaultHttpControllerActivator.Create
w3wp.exe Information: 0 : Message='MyNamespace.Controllers.MyCntrllrController', Operation=HttpControllerDescriptor.CreateController
w3wp.exe Information: 0 : Message='Selected action 'MyAction(Submission submission)'', Operation=ApiControllerActionSelector.SelectAction
w3wp.exe Information: 0 : Message='Value read='{ MyValue1: 24000, MyValue2: 2, MyValues3: 24,34, MyValue4: 0, MyValue5: 90001, MyValue6: c0, MyValue7: 16 }'', Operation=JsonMediaTypeFormatter.ReadFromStreamAsync
w3wp.exe Information: 0 : Message='Parameter 'submission' bound to the value '{ MyValue1: 24000, MyValue2: 2, MyValues3: 24,34, MyValue4: 0, MyValue5: 90001, MyValue6: c0, MyValue7: 16 }'', Operation=FormatterParameterBinding.ExecuteBindingAsync
w3wp.exe Information: 0 : Message='Model state is valid. Values: submission={ MyValue1: 24000, MyValue2: 2, MyValues3: 24,34, MyValue4: 0, MyValue5: 90001, MyValue6: c0, MyValue7: 16 }', Operation=HttpActionBinding.ExecuteBindingAsync
w3wp.exe Information: 0 : Message='Action returned 'MyNamespace.MyConclusion'', Operation=ReflectedHttpActionDescriptor.ExecuteAsync
w3wp.exe Information: 0 : Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
w3wp.exe Information: 0 : Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
w3wp.exe Information: 0 : Operation=ApiControllerActionInvoker.InvokeActionAsync, Status=200 (OK)
w3wp.exe Information: 0 : Operation=MyCntrllrController.ExecuteAsync, Status=200 (OK)
w3wp.exe Information: 0 : Message='CorsPolicyProvider selected: 'MyNamespace.WhiteListOriginPolicyProvider'', Operation=CorsPolicyProviderFactory.GetCorsPolicyProvider
w3wp.exe Information: 0 : Message='CorsPolicy selected: 'AllowAnyHeader: True, AllowAnyMethod: False, AllowAnyOrigin: False, PreflightMaxAge: null, SupportsCredentials: False, Origins: {https://www.example.com,http://localhost:22221}, Methods: {POST,OPTIONS}, Headers: {}, ExposedHeaders: {}'', Operation=WhiteListOriginPolicyProvider.GetCorsPolicyAsync
w3wp.exe Information: 0 : Message='CorsResult returned: 'IsValid: False, AllowCredentials: False, PreflightMaxAge: null, AllowOrigin: , AllowExposedHeaders: {}, AllowHeaders: {}, AllowMethods: {}, ErrorMessages: {The origin 'http://localhose' is not allowed.}'', Operation=CorsEngine.EvaluatePolicy
w3wp.exe Information: 0 : Operation=CorsMessageHandler.SendAsync, Status=200 (OK)
w3wp.exe Information: 0 : Response, Status=200 (OK), Method=POST, Url=http://myhost/myvdir/api/v1/MyCntrllr/MyAction, Message='Content-type='application/json; charset=utf-8', content-length=unknown'
w3wp.exe Information: 0 : Operation=JsonMediaTypeFormatter.WriteToStreamAsync
w3wp.exe Information: 0 : Operation=MyCntrllrController.Dispose
代码:
WhiteListOriginPolicy
public class WhiteListOriginPolicy
: CorsPolicy
{
public WhiteListOriginPolicy()
{
AllowAnyHeader = true;
AllowAnyMethod = false;
Methods.Add(HttpMethod.Post.ToString());
Methods.Add(HttpMethod.Options.ToString());
foreach (var origin in Settings.Default.WhiteListOrigins)
{
Origins.Add(origin);
}
}
}
WhiteListOrigins是来自web.config文件的StringCollection
WhiteListOriginPolicyProvider
public class WhiteListOriginPolicyProvider
: ICorsPolicyProvider
{
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult((CorsPolicy) new WhiteListOriginPolicy());
}
}
CorsPolicyProviderFactory
public class CorsPolicyProviderFactory
: ICorsPolicyProviderFactory
{
private readonly ICorsPolicyProvider _whiteListOriginsPolicyProvider = new WhiteListOriginPolicyProvider();
public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
{
return _whiteListOriginsPolicyProvider;
}
}
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableSystemDiagnosticsTracing();
config.SetCorsPolicyProviderFactory(new CorsPolicyProviderFactory());
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = RouteParameter.Optional }
);
}
}
WhiteListOriginPolicyAttribute
我认为这是多余的,但无论我是否使用
都无关紧要public class WhiteListOriginPolicyAttribute
: Attribute
, ICorsPolicyProvider
{
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult((CorsPolicy) new WhiteListOriginPolicy());
}
}
MyCntrllrController
[RoutePrefix("api/v1/MyCntrllr")]
public class MyCntrllrController
: ApiController
{
[HttpPost]
[HttpOptions]
[WhiteListOriginPolicy]
[Route("MyAction")]
public IMyConclusion MyAction([FromBody] Submission submission)
{
if (Request.Method == HttpMethod.Options)
{
return null;
}
if (null == submission)
{
var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Request content body does not contain recognizable Submission data")
};
throw new HttpResponseException(response);
}
var engine = new CalcEngine(new DataLocatorService());
var eligibility = engine.GetEligibility(submission);
return eligibility;
}
}
操作中的OPTIONS动词。
请求
OPTIONS http://myhost/myvdir/api/v1/MyCntrller/MyAction HTTP/1.1
Accept: */*
Origin: http://localhose
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type, accept
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: myhost
Content-Length: 0
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
响应的
HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 20 Nov 2013 20:32:03 GMT
Content-Length: 59
{"Message":"The origin 'http://localhose' is not allowed."}
动作中的动词。
请求
POST http://myhost/myvdir/api/v1/MyCntrller/MyAction HTTP/1.1
Accept: */*
Origin: http://localhose
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type, accept
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: myhost
Content-Length: 121
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Content-Type: application/json
{"myvalue1":24000,"myvalue2":"2","myvalues3":["24","34"],"myvalue4":0,"myvalue5":"90001","myvalue6":"c0","myvalue7":"16"}
响应的
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 20 Nov 2013 20:32:33 GMT
Content-Length: 460
_omitted_
答案 0 :(得分:4)
这不是CORS的目的。浏览器阻止了交叉源Ajax调用,因此CORS将允许目标服务器放宽这些规则。默认情况下,浏览器会阻止调用JS获取POST的结果,但它不会阻止POST(或GET)到端点。您需要实施标准授权方法,以确保只允许客户端请求端点。