2014-11-17 17 views
7

Używam DynamicPolicyProviderFactory zgodnie z opisem here. Poniżej jest moja wersja DynamicPolicyProviderFactory:Interfejs API sieci Web z włączonym CORS nie może dodać nagłówka

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); 
    } 
} 

Moje wezwanie do zarejestrowania Cors wygrać WebApiConfig.cs

config.EnableCors(); 
config.SetCorsPolicyProviderFactory(new DynamicPolicyProviderFactory(Settings.Default.AllowedDomains)); 

a moje ustawienia aplikacji są przekazywane:

<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> 

Mimo tych ustawień nagłówek Access-Control-Allow-Origin nie jest obecny na moim r odpowiedzi, jeśli zgłoszę żądanie od http://mg.domain1.com do http://localhost. Korzystam z Web Api 2.2 i Microsoft.AspNet.Cors 5.2.2.

edit: I odkryli, że jeśli mogę użyć atrybutu EnableCors na kontrolerze, lub włączyć je globalnie (config.EnableCors(new EnableCorsAttribute("*", "*", "*"));) to działa, więc to musi być coś z moim dynamicznego fabryce. Frustrujące jest to, że DynamicPolicyProvider jest kopiowany/wklejany z innego projektu, którego używam, który działa dobrze.

edit 2: Sukces ... Włączyłem tracing i znalazł błędu

The collection of headers 'accept,content-type' is not allowed 

Więc po prostu edytowany metodę GetPolicyForControllerAndOrigin do nich pozwalają. Teraz wszystko działa, z tym wyjątkiem, że jestem zdezorientowany, ponieważ nie musiałem przeskakiwać przez ten obręcz w moim drugim projekcie (tym, który skopiowałem DynamicPolicyProviderFactory z).

+1

To niesamowite, jak skomplikowane były ustawienia CORS z wieloma różnymi sposobami, w jaki sposób można je skonfigurować, gdzie każdy "prawie działa", a dokumentacja jest straszna, wszędzie i nie wyjaśnia połowy rzeczy, które ". powinien zostać wdrożony, aby działał. – pootzko

+0

@pootzko Zdecydowanie się zgadzam! Również Mike_G, czy mogę po prostu umieścić DynamicPolicyProviderFactory.cs w folderze głównym lub czy musi on przejść do określonego folderu? Co to jest: '', nie mogę go znaleźć nigdzie w pliku Web.config. Czy to jest "appSettings"? – Si8

+1

@ Si8 'DynamicPolicyProviderFactory' jest jak każda inna klasa i może być zorganizowany w dowolnym folderze kodu. dla 'MyApp.Poperties.Settings', to jest w web.config, ale jeśli chcesz UI do edycji tej konkretnej sekcji, kliknij prawym przyciskiem myszy na twoim projekcie w VS> Właściwości> Ustawienia –

Odpowiedz

4

Włącz tracing w aplikacji. Powinieneś zobaczyć błąd

The collection of headers 'accept,content-type' is not allowed 
Po prostu dodaj je do dozwolonych nagłówków dla zasady i wszystko powinno działać.