【发布时间】:2014-11-17 18:05:30
【问题描述】:
我正在使用DynamicPolicyProviderFactory,如here 所述。下面是我的 DynamicPolicyProviderFactory 版本:
public class DynamicPolicyProviderFactory : ICorsPolicyProviderFactory
{
private readonly HashSet<Regex> _allowed;
public DynamicPolicyProviderFactory(IEnumerable allowedOrigins)
{
_allowed = new HashSet<Regex>();
foreach (string pattern in allowedOrigins.Cast<string>()
.Select(Regex.Escape)
.Select(pattern => pattern.Replace("*", "w*")))
{
_allowed.Add(new Regex(pattern, RegexOptions.IgnoreCase));
}
if (_allowed.Count >= 1)
return;
//if nothing is specified, we assume everything is.
_allowed.Add(new Regex(@"https://\w*", RegexOptions.IgnoreCase));
_allowed.Add(new Regex(@"http://\w*", RegexOptions.IgnoreCase));
}
public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
{
var route = request.GetRouteData();
var controller = (string)route.Values["controller"];
var corsRequestContext = request.GetCorsRequestContext();
var originRequested = corsRequestContext.Origin;
var policy = GetPolicyForControllerAndOrigin(controller, originRequested);
return new CustomPolicyProvider(policy);
}
private CorsPolicy GetPolicyForControllerAndOrigin(string controller, string originRequested)
{
// Do lookup to determine if the controller is allowed for
// the origin and create CorsPolicy if it is (otherwise return null)
if (_allowed.All(a => !a.Match(originRequested).Success))
return null;
var policy = new CorsPolicy();
policy.Origins.Add(originRequested);
policy.Methods.Add("GET");
policy.Methods.Add("POST");
policy.Methods.Add("PUT");
policy.Methods.Add("DELETE");
return policy;
}
}
public class CustomPolicyProvider : ICorsPolicyProvider
{
private readonly CorsPolicy _policy;
public CustomPolicyProvider(CorsPolicy policy)
{
this._policy = policy;
}
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(this._policy);
}
}
我注册 cors 的调用赢得了 WebApiConfig.cs
config.EnableCors();
config.SetCorsPolicyProviderFactory(new DynamicPolicyProviderFactory(Settings.Default.AllowedDomains));
我的应用程序设置正在通过:
<MyApp.Properties.Settings>
<setting name="AllowedDomains" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>http://localhost</string>
<string>http*://*.domain1.com</string>
<string>http*://*.domain2.com</string>
</ArrayOfString>
</value>
</setting>
</MyApp.Properties.Settings>
尽管有这些设置,但如果我从http://mg.domain1.com 向http://localhost 发出请求,我的回复中不会出现Access-Control-Allow-Origin 标头。我正在使用 Web Api 2.2 和 Microsoft.AspNet.Cors 5.2.2。
编辑:我发现如果我在控制器上使用EnableCors 属性,或者全局启用它(config.EnableCors(new EnableCorsAttribute("*", "*", "*"));)它可以工作,所以它一定与我的动态工厂有关。令人沮丧的是,DynamicPolicyProvider 是从我正在使用的另一个项目中复制/粘贴的,效果很好。
编辑2:成功!...我启用tracing并发现错误
The collection of headers 'accept,content-type' is not allowed
所以我只是编辑了GetPolicyForControllerAndOrigin 方法以允许它们。现在一切正常,除了我很困惑,因为我不必在我的另一个项目(我从中复制 DynamicPolicyProviderFactory 的那个项目)中跳过这一圈。
【问题讨论】:
-
令人惊讶的是,他们使用多种不同的方式设置 CORS 设置有多复杂,您可以在每个“几乎可以工作”的地方进行设置,而且文档很糟糕,到处都是,没有解释你应该实现一半的东西才能让它工作。
-
@pootzko 我绝对同意!还有 Mike_G,我可以将 DynamicPolicyProviderFactory.cs 放在根文件夹中还是必须放在某个文件夹中?这是什么:
</MyApp.Properties.Settings>,我在 Web.config 的任何地方都找不到它。那是appSettings吗? -
@Si8
DynamicPolicyProviderFactory就像任何其他类一样,可以组织在任何代码文件夹下。对于MyApp.Poperties.Settings,它位于 web.config 中,但如果您想要一个用于编辑该特定部分的 UI,请在 VS > Properties > Settings 中右键单击您的项目 -
这有帮助,谢谢。这样我就不用在每个 API 文件上面加上 [EnableCors()] 了吗?
-
不,只需使用
<string>http*://mysite.com</string>(将访问 http 和 https)或类似<string>http*://*.mysite.com</string>的东西来包含子域。
标签: c# asp.net asp.net-web-api asp.net-web-api2