2015-07-24 23 views
5

Ich möchte einige zusätzliche Ansprüche an einen Principal während der Authentifizierung hinzufügen. Ich versuche, einen benutzerdefinierten ClaimsAuthenticationManager in meinem MVC 4,5 Projekt zu implementieren, die Windows-Authentifizierung verwendet:ClaimsAuthenticationManager.Authenticate wird nie aufgerufen

namespace Project.Infrastructure 
{ 
    public class ClaimsTransformer : ClaimsAuthenticationManager 
    { 
     public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
     { 
      if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true) 
      { 
       ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "Admin")); 
      } 

      return incomingPrincipal; 
     } 
    } 
} 

Ich habe die web.config einrichten, um meine benutzerdefinierte Klasse zu verwenden:

<configSections> 
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> 
</configSections> 

und

<system.identityModel> 
    <identityConfiguration> 
     <claimsAuthenticationManager type="Project.Infrastructure.ClaimsTransformer, [AssemblyName]" /> 
    </identityConfiguration> 
</system.identityModel> 

Aber die Authentifizieren Methode wird nie aufgerufen. Fehle ich etwas?

+0

Haben Sie das Berechtigungsmodul für Ansprüche Ihrer .config hinzugefügt? –

+1

Nein, die Autorisierung wird nicht angepasst. Es ist mein Verständnis, dass die zwei getrennt und verschieden sind und man nicht von dem anderen abhängig ist. Ist das nicht korrekt? – newmanth

Antwort

4

Der fehlende Schritt ist, dass Sie ein HTTP-Modul hinzufügen müssen, um das alles abzuschalten.

So müssen Sie eine Klasse, die wie folgt aussieht:

public class MyClaimsAuthenticationModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     context.PostAuthenticateRequest += Context_PostAuthenticateRequest; 
    } 

    public void Dispose() 
    { 
     // Nothing to dispose, method required by IHttpModule 
    } 

    void Context_PostAuthenticateRequest(object sender, EventArgs e) 
    { 
     var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager; 
     if (transformer != null) 
     { 
      var context = ((HttpApplication)sender).Context; 
      var principal = context.User as ClaimsPrincipal; 
      var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, principal); 

      context.User = transformedPrincipal; 
      Thread.CurrentPrincipal = transformedPrincipal; 
     } 
    } 
} 

Dadurch wird der Transformator Sie in der web.config angegeben abholen und auf sie authentifizieren rufen, dann bringen Sie den zurückgegebenen Haupt zu der Httpcontext und der aktuelle Thread.

Sie müssen auch so etwas wie die folgenden in Ihrer web.config:

<system.webServer> 
    <modules> 
    <add name="MyClaimsAuthenticationModule" type="MyApplication.MyHttpModels.MyClaimsAuthenticationModule, MyApplicationAssembly" /> 
    </modules> 
</system.webServer> 

aktualisieren

Sie können natürlich den Code aus dem Verfahren setzen Context_PostAuthenticationRequest in der PostAuthenticateRequest Handler in Ihre Global.asax.cs Klassendatei. Jedoch bevorzuge ich, die Verantwortungen der Klassen klein zu halten, also gehe ich für eine Implementierung von IHttpModule, so dass das Modul seine Sache macht und es ist offensichtlich, was das ist, und es ist getrennt von anderen Dingen, die in verschiedenen Stadien von geschehen können die Pipeline.

Wenn Ihre Datei Global.asax.cs klein ist, gibt es kein Problem mit dem Code dort. Es sollte noch funktionieren. Sie mischen jedoch Verantwortlichkeiten in der Klasse und es könnte in Zukunft unhandlich werden.

+1

MSDN war nicht klar, dass ClaimsAuthenticationManager nicht für Windows-Authentifizierung aufgerufen wird und manuell verdrahtet werden muss. Danke ... genau das, was ich gesucht habe. Bin ich richtig in der Annahme, dass ich auch die Verbindung in einer Application_PostAuthenticateRequest-Methode ausführen könnte, wenn ich bereits eine global.asax-Datei habe? – newmanth

+0

Ja, ich nehme an, Sie könnten. Ich bin persönlich kein Fan davon, ich ziehe es vor, Dinge in Klassen zu stellen, die IHttpModule implementieren, um Probleme getrennt zu halten. (d. h. Dieses Modul macht eine Sache) Wenn Ihr Global Asax klein ist und klein bleiben wird, sehe ich kein Problem damit, den Code dorthin zu setzen. Offensichtlich, wenn es größer wird, dann weil es zu viele Dinge macht. Also müssen Sie wirklich darüber nachdenken, die verschiedenen Verantwortlichkeiten zu trennen. –

+0

Warum sollten wir den Umweg über System.IdentityModel.ClaimsAuthenticationManager nehmen? - Ich meine, warum kann ich nicht einfach den Code des benutzerdefinierten 'ClaimsTransformer' direkt in das' MyClaimsAuthenticationModule' schreiben? – Efrain

0

Rufen Sie die Authenticate-Methode mit so etwas auf und die Authentifizierung findet nicht statt?

ClaimsTransformer manager = new ClaimsTransformer(); 
manager.Authenticate("resource", incomingPrincipal) 

Sie möchten die „Rückkehr incomingPrincipal“ aus dem Inneren der ClaimsTransformer Klasse mit einem Aufruf ersetzen:

return base.Authenticate(resourceName, incomingPrincipal); 

auch, warum Sie die Windows-Authentifizierung benötigen Sie?

+1

Die base.Authentication-Methode führt nichts aus.Wörtlich ist es: 'public virtual ClaimsPrincipal Authenticate (Zeichenfolge resourceName, ClaimsPrincipal incomingPrincipal) { return incomingPrincipal; } ' –

Verwandte Themen