Access-control-allow-origin с несколькими доменами
в моем web.config я хотел бы указать более одного домена для директивы access-control-allow-origin. Я не хочу использовать *. Я пробовал этот синтаксис:
<add name="Access-Control-Allow-Origin" value="http://localhost:1506, http://localhost:1502" />
этот
<add name="Access-Control-Allow-Origin" value="http://localhost:1506 http://localhost:1502" />
этот
<add name="Access-Control-Allow-Origin" value="http://localhost:1506; http://localhost:1502" />
и этот
<add name="Access-Control-Allow-Origin" value="http://localhost:1506" />
<add name="Access-Control-Allow-Origin" value="http://localhost:1502" />
но ни один из них не работает. Каков правильный синтаксис ?
8 ответов:
здесь может быть только один
Access-Control-Allow-Origin
заголовок ответа, и этот заголовок может иметь только одно исходное значение. Поэтому, чтобы заставить это работать, вам нужно иметь некоторый код, который:
- схватил
Origin
заголовок запроса.- проверяет, является ли исходное значение одним из значений белого списка.
- если он действителен, устанавливает
Access-Control-Allow-Origin
заголовок с этим значением.Я не думаю, что есть любой способ сделать это исключительно через сеть.конфиг.
if (ValidateRequest()) { Response.Headers.Remove("Access-Control-Allow-Origin"); Response.AddHeader("Access-Control-Allow-Origin", Request.UrlReferrer.GetLeftPart(UriPartial.Authority)); Response.Headers.Remove("Access-Control-Allow-Credentials"); Response.AddHeader("Access-Control-Allow-Credentials", "true"); Response.Headers.Remove("Access-Control-Allow-Methods"); Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); }
для IIS 7.5+ и перезаписи 2.0 вы можете использовать:
<system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" /> <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" /> </customHeaders> </httpProtocol> <rewrite> <outboundRules> <clear /> <rule name="AddCrossDomainHeader"> <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="true"> <add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?domain1\.com|(.+\.)?domain2\.com|(.+\.)?domain3\.com))" /> </conditions> <action type="Rewrite" value="{C:0}" /> </rule> </outboundRules> </rewrite> </system.webServer>
объяснение переменной сервера
RESPONSE_Access_Control_Allow_Origin
часть:
В Rewrite вы можете использовать любую строку послеRESPONSE_
и он создаст заголовок ответа, используя остальную часть слова в качестве имени заголовка (в этом случае Access-Control-Allow-Origin). Rewrite использует подчеркивания " _ "вместо тире" - "(rewrite преобразует их в тире)объяснение переменной сервера
HTTP_ORIGIN
:
Аналогично, в Rewrite вы можете захватить любой заголовок запроса с помощьюHTTP_
как префикс. Те же правила с тире (используйте подчеркивания "_" вместо тире "-").
В Интернете.API этот атрибут может быть добавлен с помощью
Microsoft.AspNet.WebApi.Cors
как подробно на http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-apiв MVC вы можете создать атрибут фильтра, чтобы сделать эту работу за вас:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class EnableCorsAttribute : FilterAttribute, IActionFilter { private const string IncomingOriginHeader = "Origin"; private const string OutgoingOriginHeader = "Access-Control-Allow-Origin"; private const string OutgoingMethodsHeader = "Access-Control-Allow-Methods"; private const string OutgoingAgeHeader = "Access-Control-Max-Age"; public void OnActionExecuted(ActionExecutedContext filterContext) { // Do nothing } public void OnActionExecuting(ActionExecutingContext filterContext) { var isLocal = filterContext.HttpContext.Request.IsLocal; var originHeader = filterContext.HttpContext.Request.Headers.Get(IncomingOriginHeader); var response = filterContext.HttpContext.Response; if (!String.IsNullOrWhiteSpace(originHeader) && (isLocal || IsAllowedOrigin(originHeader))) { response.AddHeader(OutgoingOriginHeader, originHeader); response.AddHeader(OutgoingMethodsHeader, "GET,POST,OPTIONS"); response.AddHeader(OutgoingAgeHeader, "3600"); } } protected bool IsAllowedOrigin(string origin) { // ** replace with your own logic to check the origin header return true; } }
затем либо включить его для конкретных действий / контроллеров:
[EnableCors] public class SecurityController : Controller { // *snip* [EnableCors] public ActionResult SignIn(Guid key, string email, string password) {
или добавить его для всех контроллеров в глобальной.асакс.cs
protected void Application_Start() { // *Snip* any existing code // Register global filter GlobalFilters.Filters.Add(new EnableCorsAttribute()); RegisterGlobalFilters(GlobalFilters.Filters); // *snip* existing code }
прочитав каждый ответ и попробовав их, ни один из них не помог мне. То, что я нашел во время поиска в другом месте, - это то, что вы можете создать пользовательский атрибут, который затем можно добавить в свой контроллер. Он перезаписывает EnableCors и добавляет в него домены с белым списком.
Это решение работает хорошо, потому что оно позволяет вам иметь белые домены в webconfig (appsettings) вместо того, чтобы кодировать их в атрибуте EnableCors на вашем компьютере контроллер.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class EnableCorsByAppSettingAttribute : Attribute, ICorsPolicyProvider { const string defaultKey = "whiteListDomainCors"; private readonly string rawOrigins; private CorsPolicy corsPolicy; /// <summary> /// By default uses "cors:AllowedOrigins" AppSetting key /// </summary> public EnableCorsByAppSettingAttribute() : this(defaultKey) // Use default AppSetting key { } /// <summary> /// Enables Cross Origin /// </summary> /// <param name="appSettingKey">AppSetting key that defines valid origins</param> public EnableCorsByAppSettingAttribute(string appSettingKey) { // Collect comma separated origins this.rawOrigins = AppSettings.whiteListDomainCors; this.BuildCorsPolicy(); } /// <summary> /// Build Cors policy /// </summary> private void BuildCorsPolicy() { bool allowAnyHeader = String.IsNullOrEmpty(this.Headers) || this.Headers == "*"; bool allowAnyMethod = String.IsNullOrEmpty(this.Methods) || this.Methods == "*"; this.corsPolicy = new CorsPolicy { AllowAnyHeader = allowAnyHeader, AllowAnyMethod = allowAnyMethod, }; // Add origins from app setting value this.corsPolicy.Origins.AddCommaSeperatedValues(this.rawOrigins); this.corsPolicy.Headers.AddCommaSeperatedValues(this.Headers); this.corsPolicy.Methods.AddCommaSeperatedValues(this.Methods); } public string Headers { get; set; } public string Methods { get; set; } public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return Task.FromResult(this.corsPolicy); } } internal static class CollectionExtensions { public static void AddCommaSeperatedValues(this ICollection<string> current, string raw) { if (current == null) { return; } var paths = new List<string>(AppSettings.whiteListDomainCors.Split(new char[] { ',' })); foreach (var value in paths) { current.Add(value); } } }
Я нашел это руководство в интернете и он работал как шарм :
Я думал, что оставлю это здесь для тех, кто нуждается.
загляните в библиотеку Thinktecture IdentityModel-она имеет полную поддержку CORS:
http://brockallen.com/2012/06/28/cors-support-in-webapi-mvc-and-iis-with-thinktecture-identitymodel/
и он может динамически излучать ACA-происхождение, которое вы хотите.
мне удалось решить эту проблему в коде обработки запроса, следуя совету "monsur".
string origin = WebOperationContext.Current.IncomingRequest.Headers.Get("Origin"); WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", origin);
вы можете использовать owin middle ware для определения политики cors, в которой вы можете определить несколько источников cors
return new CorsOptions { PolicyProvider = new CorsPolicyProvider { PolicyResolver = context => { var policy = new CorsPolicy() { AllowAnyOrigin = false, AllowAnyMethod = true, AllowAnyHeader = true, SupportsCredentials = true }; policy.Origins.Add("http://foo.com"); policy.Origins.Add("http://bar.com"); return Task.FromResult(policy); } } };
вам нужно лишь : - добавить глобальный.asax к вашему проекту,
- удалить из вашего интернета.конфиг.
- после добавления в метод Application_BeginRequest глобального.асакс это:HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*"); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept"); HttpContext.Current.Response.End(); }
Я надеюсь, что это поможет. это работа для меня.