Wie mache ich die CORS-Authentifizierung in WebAPI 2?

74

Das Szenario ist einfach. Ich muss mich von einem anderen Server (anders als der API-Server) anmelden, um das Zugriffstoken abzurufen.

Ich habe das Microsoft.Owin.CorsPaket auf dem API-Server installiert . In der Startup.Auth.csDatei unter habe public void ConfigureAuth(IAppBuilder app)ich hinzugefügt

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

In WebApiConfig.cs, unter public static void Register(HttpConfiguration config), fügte ich in diesen Zeilen hinzu:

// Cors
var cors = new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS");
config.EnableCors(cors);

Was soll ich noch ändern?

Blaise
quelle
6
app.UseCors (CorsOptions.AllowAll) - aktiviert CORS für alle Cross-Origin-Anfragen an Ihre Site. config.EnableCors (..) aktiviert nur CORS für Web-API
Konstantin Tarkus

Antworten:

78

Schau dir an, was ich gefunden habe!

Fügen Sie einige benutzerdefinierte Header hinzu <system.webServer>.

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
  </customHeaders>
</httpProtocol>

Dann kann ich die CORS-Authentifizierung durchführen.

Blaise
quelle
4
Ich habe keine Ahnung, wie ich das ohne Ihren Beitrag herausgefunden hätte. Vielen Dank! In der Web-API-Dokumentation werden diese Konfigurationsanforderungen nicht erwähnt ... goo.gl/s9K6o2 & goo.gl/G8jKG0
TheFastCat
2
Leider wird in der OWIN-Authentifizierungspipeline 1) die Antwort überschrieben, die ich bereits über den Kontext geschrieben habe. Request.Headers als Teil der OWIN-Middleware 2) Auch bei konfigurierten benutzerdefinierten Richtlinien wird dies ignoriert OWIN cors für die "/ token" -Anforderung. Zumindest zu Testzwecken bin ich mir nicht sicher, ob ich im Moment eine große Auswahl habe.
1
Ich denke, was wirklich passieren sollte, ist, dass wir die Token-Methode mit dem sogenannten Login in den Account-Controller einbinden sollten, dann würde die Standard-Cors-Konfiguration den Job erledigen.
Tim Hong
7
Dies ist keine gute Lösung. Es funktioniert, aber es entspricht dem Ausschalten Ihrer Firewall, anstatt sie ordnungsgemäß zu konfigurieren.
Piotr Stulinski
2
Ich stimme dir nicht zu. CORS ist für nichts eine Lösung. Eine Firewall schützt den Client, aber CORS wird (falsch) verwendet, um den Server zu schützen, aber eine einfache Client-Änderung der Anforderungsheader und Sie sind golden. Verwenden Sie einfach zB chrome --disable-web-security flag oder suchen Sie nach Allow-Control-Allow-Origin: * Chrome-Erweiterung.
Peheje
50

Ich hatte viele Versuche und Irrtümer, um es für den AngularJS-basierten Webclient einzurichten.
Für mich funktionieren die folgenden Ansätze mit ASP.NET WebApi 2.2 und OAuth-basierten Diensten.

  1. Installieren Sie das Microsoft.AspNet.WebApi.CorsNuget-Paket.
  2. Installieren Sie das Microsoft.Owin.CorsNuget-Paket.
  3. Fügen Sie config.EnableCors(new EnableCorsAttribute("*", "*", "GET, POST, OPTIONS, PUT, DELETE"));die obige WebApiConfig.Register(config);Zeile in der Datei Startup.cs hinzu .
  4. In app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);auf die Startup.Auth.cs Datei. Dies muss vor dem Anruf erfolgenIAppBuilder.UseWebApi
  5. Entfernen Sie alle XML-Einstellungen, die Blaise vorgenommen hat.

Ich habe hier viele Setup-Variationen und Kombinationen für Stackoverflow- oder Blog-Artikel gefunden . Blaises Ansatz kann also falsch sein oder auch nicht. Es ist nur eine andere Einstellung, denke ich.

Youngjae
quelle
4
Dies könnte das folgende Problem verursachen: aspnetwebstack.codeplex.com/workitem/1539
Milen Kovachev
2
Ich habe CORS in meinen OWIN- und Web-API-Konfigurationen mit app.UseCorsbzw. config.EnableCorsMethoden aktiviert , aber der OWIN- /tokenEndpunkt scheint speziell behandelt zu werden und sendet in der Antwort nicht den HTTP-Header Access-Control-Allow-Origin. Dies gilt auch dann, wenn die unten stehende benutzerdefinierte Richtlinienlösung von Konstantin Tarkus implementiert wird.
1
Sie benötigen ein Nuget-Paket "Microsoft.AspNet.WebApi.Cors", um Klassen und Methoden für Schritt 1 zu haben.
Jan Zahradník
3
Ich hatte zu installieren Microsoft.Owin.Corsals auch
Galdin
33

Nach vielen Stunden des Suchens und Betrachtens vieler verschiedener Lösungen habe ich es geschafft, dies wie folgt zum Laufen zu bringen.

Es gibt eine Reihe von Gründen, warum dies geschieht. Höchstwahrscheinlich haben Sie CORS am falschen Ort aktiviert oder es ist zweimal oder gar nicht aktiviert.

Wenn Sie die Web-API und den Owin-Token-Endpunkt verwenden, müssen Sie alle Verweise auf CORS in Ihrer Web-API-Methode entfernen und die richtige owin-Methode hinzufügen, da Web-APIs nicht mit dem Token-Endpunkt funktionieren, während Owin-Cors für beide Web-Versionen funktionieren API- und Token-Authentifizierungsendpunkte. Beginnen wir also:

  1. Stellen Sie sicher, dass Sie das Owin Cors-Paket installiert haben. Entfernen Sie alle Zeilen, die Sie haben, z. B. config.EnableCors (); aus Ihrer WebAPIconfig.cs-Datei

  2. Gehen Sie zu Ihrer Datei startup.cs und stellen Sie sicher, dass Sie Owin Cors ausführen, bevor eine der anderen Konfigurationen ausgeführt wird.

    app.UseCors (Microsoft.Owin.Cors.CorsOptions.AllowAll); ConfigureAuth (App);

  3. Wenn Sie immer noch Probleme haben, gehen Sie zu: Startup.Auth.cs und stellen Sie sicher, dass Ihre ConfigureAuth-Methode Folgendes enthält (Sie sollten dies nicht benötigen, wenn Ihre Datei startup.cs korrekt ist).

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

Piotr Stulinski
quelle
2
Danke @Piotr, das ist die wirklich funktionierende Antwort. Kann Blaise dies bitte als echte Antwort markieren? Bei allen anderen Antworten funktioniert entweder OWIN / Token oder WebAPI, während sie nicht zusammenarbeiten können. In meinem Fall führt das Hinzufügen von XML in Web.config plus config.EnableCors (...) dazu, dass doppelte Header [Access-Control-Allow-Headers] hinzugefügt werden, was in Chrome verboten ist.
Joe Lau
Auch ich habe Probleme mit doppelten Headern, nachdem ich sowohl OWIN- als auch Web-API-Cors in das Projekt aufgenommen habe. Aber wie @Piotr in der Antwort feststellte, reicht nur OWIN CORS aus, um sich darum zu kümmern.
Dipendu Paul
1
Dies ist die beste Antwort. Vielen Dank. Möglicherweise benötigen Sie zusätzlich das Microsoft.AspNet.WebApi.OwinSelfHost-Paket und das Microsoft.Owin.Cors-Paket, um die UseCors-Funktion von IAppBuilder (App) zu verwenden
janaka aravinda
21

web.config

<appSettings>
  <add key="cors:Origins" value="*" />
  <add key="cors:Headers" value="*" />
  <add key="cors:Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
</appSettings>

Startup.cs

var appSettings = WebConfigurationManager.AppSettings;

// If CORS settings are present in Web.config
if (!string.IsNullOrWhiteSpace(appSettings["cors:Origins"]))
{
    // Load CORS settings from Web.config
    var corsPolicy = new EnableCorsAttribute(
        appSettings["cors:Origins"],
        appSettings["cors:Headers"],
        appSettings["cors:Methods"]);

    // Enable CORS for ASP.NET Identity
    app.UseCors(new CorsOptions
    {
        PolicyProvider = new CorsPolicyProvider
        {
            PolicyResolver = request =>
                request.Path.Value == "/token" ?
                corsPolicy.GetCorsPolicyAsync(null, CancellationToken.None) :
                Task.FromResult<CorsPolicy>(null)
        }
    });

    // Enable CORS for Web API
    config.EnableCors(corsPolicy);
}

Hinweis : app.UserCors(...)Sollte vor dem Konfigurieren der ASP.NET-Identität aufgerufen werden.

Quelle: Starterkit für ASP.NET-Webanwendungen (ASP.NET-Web-API, Identität, SignalR)

Konstantin Tarkus
quelle
Ich habe dies implementiert und bin überrascht, dass die HTTP-Antwort für die Anforderung "/ token" keinen Header für Access-Control-Allow-Origin enthält, um zu überprüfen, ob die Ausführung des Richtliniencodes im Debugger gültig ist.
Seltsamerweise verschwand das Problem mit "/ token", nachdem CORS über web.config aktiviert wurde, indem der Antwortheader manuell hinzugefügt wurde, nicht über eine OWIN- oder Web-API-CORS-Konfiguration, dann entfernt und meine API-Konfigurationen wieder aktiviert wurden. Ich bin mir nicht sicher, was los ist, aber das Problem ist jetzt weg.
1
Beachten Sie, dass die Reihenfolge, in der Sie .EnableCors()Ihre OWIN-Pipeline platzieren, von Bedeutung ist. Sie möchten es vor andere OWIN-Middleware stellen.
Konstantin Tarkus
Ist dies die web.config für die API-Website oder für die Client-Website?
Manuel Hernandez
@KonstantinTarkus Hallo, ich möchte nur http-Anfragen von bestimmten URLs zulassen. Was soll ich anstelle von Wert in <add key = "cors: Origins" value = "*" /> setzen? Die einzige URL, die eine Anfrage stellen kann, ist localhost: 777. ?
Alex
15

Um die Antwort von Youngjae zu erläutern, finden Sie unter http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web- ein großartiges Tutorial zum Einrichten von OWIN mit Web-API und zum Aktivieren von CORS. api-2-owin-asp-net-identität /

Sie möchten das NuGet-Paket für CORS mit dem folgenden Befehl hinzufügen:
Install-Package Microsoft.Owin.Cors -Version 2.1.0

Dann füge hinzu
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

zu Ihrer Konfigurationsmethode in Startup.cs, damit es ungefähr so ​​aussieht:

public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();
    ConfigureOAuth(app);
    WebApiConfig.Register(config);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);
}
Yaron
quelle
8
Das funktioniert bei mir nicht. Und ich denke, die ursprüngliche Frage war genau das, warum app.UseCors (Microsoft.Owin.Cors.CorsOptions.AllowAll); funktioniert nicht.
Milen Kovachev
Ich habe CORS in meinen OWIN- und Web-API-Konfigurationen mit app.UseCorsbzw. config.EnableCorsMethoden aktiviert , aber der OWIN- /tokenEndpunkt scheint speziell behandelt zu werden und sendet in der Antwort nicht den HTTP-Header Access-Control-Allow-Origin. Dies gilt auch dann, wenn die unten stehende benutzerdefinierte Richtlinienlösung von Konstantin Tarkus implementiert wird.
9

Die Antwort für mich wurde bei gefunden

Web Api 2 Preflight CORS-Anfrage für Bearer Token

Insbesondere die / Token-Anforderung, die eine Implementierung von OAuthAuthorizationServerProvider.GrantResourceOwnerCredentials verwendet, fügte den Header erneut hinzu. Fügen Sie das OWIN CORS-Zeug vor jeder anderen OWIN-Konfiguration hinzu und entfernen Sie den Header aus GrantResourceOwnerCredentials gemäß diesem Link und voila. Viel Glück.

Dale Holborow
quelle
Du hast meinen ganzen Tag gerettet.
Sumit
9

Ich möchte nur meine Erfahrungen teilen. Ich verbrachte den halben Tag damit, meinen Kopf zu schlagen und zu versuchen, ihn zum Laufen zu bringen. Ich las zahlreiche Artikel und SO-Fragen und fand am Ende heraus, was los war.

Die Linie

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

war nicht der erste in der StartupKlasseConfiguration Methode. Als ich es nach oben schob, fing alles magisch an zu arbeiten.

Und keine benutzerdefinierten Header in web.configoderconfig.EnableCors(corsPolicy); oder etwas anderes waren nicht erforderlich.

Hoffe, dies wird jemandem helfen, etwas Zeit zu sparen.

Andrew
quelle
1
sparte mir 30 Minuten bevor mein Auftrag fällig war :) danke! #magic lol
Norman Bentley
Selbst wenn ich dies als erste Zeile in der Konfigurationsmethode der Startklasse hinzufüge, wird der Fehler angezeigt. Aber wenn ich die Konfiguration zusammen mit dieser Zeile hinzufüge, wird das doppelte Problem ausgelöst.
Bomaboom
4

Hier finden Sie die verschiedenen Möglichkeiten, wie Sie CORS in verschiedenen Bereichen aktivieren können: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Wie auch immer, ich hatte das gleiche Problem und durch das Hinzufügen der Header auf unterschiedliche Weise konnte ich nicht die vollständige Lösung erhalten.

Ich habe herausgefunden, dass der IIS Handler verwendet, die Ihre CORS-Webanwendungskonfiguration überschreiben, wenn Sie nicht das Gegenteil angeben.

In meinem Fall musste ich auch die Verwendung von IIS-Handlern entfernen, indem ich die folgende Konfiguration in der Haupt-Web.config meiner Anwendung hinzufügte:

<system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>

Beachten Sie, dass diese Konfiguration je nach Typ standardmäßig festgelegt sein kann, wenn Sie ein neues Projekt erstellen. Wenn Sie jedoch von vorne beginnen, müssen Sie diese Konfiguration wahrscheinlich hinzufügen.

Seba Cervantes
quelle
Ja! Das hat mich so nervt, dass ich während der Entwicklung JSONP verwendet habe. Wie Sie sagen, von vorne angefangen.
Tiger mit Gitarren
2

Das Hinzufügen von Kunden-Headern gibt Ihnen möglicherweise nicht so viel Freiheit beim Anpassen Ihrer Sicherheitsanforderungen. Es öffnet der Welt alle anderen Teile der API. Der folgende Code führt dies nur für "Token" aus, und der andere Teil der API des Controllers sollte über die EableCors-Annotation erfolgen.

public void ConfigureAuth(IAppBuilder app)
{
    //other stuff
    app.Use(async (context, next) =>
    {
        IOwinRequest req = context.Request;
        IOwinResponse res = context.Response;
        if (req.Path.StartsWithSegments(new PathString("/Token")))
        {
            var origin = req.Headers.Get("Origin");
            if (!string.IsNullOrEmpty(origin))
            {
                res.Headers.Set("Access-Control-Allow-Origin", origin);
            }
            if (req.Method == "OPTIONS")
            {
                res.StatusCode = 200;
                res.Headers.AppendCommaSeparatedValues("Access-Control-    Allow-Methods", "GET", "POST");
                res.Headers.AppendCommaSeparatedValues("Access-Control-    Allow-Headers", "authorization", "content-type");
                return;
            }
        }
        await next();
    });
    //other stuff
}

Befolgen Sie die Anweisungen hier, um Cors zu aktivieren .

Tim Hong
quelle
1

Wenn Sie OWIN-Middleware für die Verarbeitung von CORS verwenden, müssen Sie keine Header in der Datei WebAPIConfig oder web.config hinzufügen. Ja, das Hinzufügen der Header zur Datei "web.config" funktioniert, wenn Sie öffentlichen Zugriff wünschen. Wenn Sie den Zugriff jedoch auf der Grundlage einer Whitelist (Domänen) einschränken müssen, möchten Sie nicht mehr " Alle Zugriffe zulassen" .

Mit OWINS können wir dies bewältigen, indem wir diesen Handler implementieren:

OAuthAuthorizationServerProvider.MatchEndpoint

Mit diesem Handler können wir die Anforderungsmethode (OPTIONEN, POST ...) erkennen und feststellen, ob die Anforderung als Autorisierungs- oder Token-Endpunkt behandelt werden soll. Dies ist der Bereich, in dem Logik hinzugefügt werden kann, um den Origin-Header (Anforderung) zu überprüfen und zu überprüfen, ob diese Domäne zulässig sein soll, indem der Antwortheader Access-Control-Allow-Origin hinzugefügt wird.

string origin = context.Request.Headers.Get("Origin");
var found = IsDomainAllowed(origin);
 if (found){
      context.Response.Headers.Add("Access-Control-Allow-Origin",
                             new string[] { origin });
 }      

Weitere Hintergrundinformationen hierzu finden Sie unter folgendem Link: http://www.ozkary.com/2016/04/web-api-owin-cors-handling-no-access.html

Ozkary
quelle
0

Komplette Lösung. Sie müssen nur einige Dateien ändern, funktioniert für mich.

Global.ascx

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    } }

WebApiConfig.cs

Alle Anfragen haben diesen Code aufgerufen.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    } }

Einige Controller

Nichts zu ändern.

Web.config

Sie müssen Handler in Ihrer web.config hinzufügen

<configuration> 
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>   
  </system.webServer> 
</configuration>
Jonas Ribeiro
quelle