2014-07-17 3 views
6

Je développe une application Web avec un jeton support Asp.Net 5 MVC, Owin et Oauth2 en tant que type d'authentification.Valeurs de revendication complexes dans .NET Framework avec System.Security.Claims

Après this guide qui ajoute une réclamation personnalisée complexe JSON sérialisé à une instance de Microsoft.IdentityModel.Claims.ClaimsIdentity avec succès, je l'ai essayé de reproduire le même exemple en utilisant le ClaimsIdentity sur l'espace de noms System.Security.Claims. Malheureusement, il semble que si l'on ajoute un complexClaim à l'instance ClaimsIdentity, les informations de type de classe dérivée sont perdues et la revendication est stockée sous la forme System.Security.Claims.Claim.

var complexClaim = new ComplexClaim<UKPassport>(@"http://it.test/currentpassport", passport); 
var claims = new List<Claim>() { complexClaim }; 
identity.AddClaims(claims); 

Lorsque je tente de récupérer la demande d'identité, jetant à à un type ComplexClaim<UKPassport> se traduit par une valeur nulle. Le même exemple fonctionne parfaitement en utilisant Microsoft.IdentityModel.Claims.

Des indices?

Voici le code complet porté:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Newtonsoft.Json; 
using System.Security.Claims; 

namespace ConsoleApplication1 
{ 
    class Program { 
    private static ClaimsIdentity identity = new ClaimsIdentity(); 

    static void Main(string[] args) 
    { 
     var oldPassport = CreatePassport(); 
     identity.AddPassport(oldPassport); 

     var britishCitizen = identity.IsBritishCitizen(); 
     var hasExpired = identity.IsCurrentPassportExpired(); 
     Console.WriteLine(hasExpired); 
     Console.ReadLine(); 
    } 

    private static UKPassport CreatePassport() 
    { 
     var passport = new UKPassport(
      code: PassportCode.GBR, 
      number: 123456789, 
      expiryDate: DateTime.Now); 

     return passport; 
    } 
} 

    public static class ClaimsIdentityExtensions { 
    public static void AddPassport(this ClaimsIdentity identity, UKPassport passport) 
    { 
     var complexClaim = new ComplexClaim<UKPassport>(@"http://it.test/currentpassport", passport); 

     var claims = new List<Claim>() { complexClaim }; 
     identity.AddClaims(claims); 
    } 

    public static bool IsCurrentPassportExpired(this ClaimsIdentity identity) 
    { 
     var passport = GetPassport(identity, @"http://it.test/currentpassport"); 
     return DateTime.Now > passport.ExpiryDate; 
    } 

    public static bool IsBritishCitizen(this ClaimsIdentity identity) 
    { 
     var passport = GetPassport(identity, @"http://it.test/currentpassport"); 
     return passport.Code == PassportCode.GBR; 
    } 

    private static UKPassport GetPassport(this ClaimsIdentity identity, string passportType) 
    { 
     var passportClaim = identity.Claims.FirstOrDefault<Claim>(c=>c.Type == @"http://it.test/currentpassport") as ComplexClaim<UKPassport>; 
     return passportClaim.Value; 
    } 
} 

    public enum PassportCode 
    { 
     GBR, 

     GBD, 

     GBO, 

     GBS, 

     GBP, 

     GBN 
    } 


    public class ComplexClaim<T> : Claim where T : ClaimValue 
    { 
     public ComplexClaim(string claimType, T claimValue) 
      : this(claimType, claimValue, string.Empty) 
     { 
     } 

     public ComplexClaim(string claimType, T claimValue, string issuer) 
      : this(claimType, claimValue, issuer, string.Empty) 
     { 
     } 

     public ComplexClaim(string claimType, T claimValue, string issuer, string originalIssuer) 
      : base(claimType, claimValue.ToString(), claimValue.ValueType(), issuer, originalIssuer) 
     { 
     } 

     public new T Value 
     { 
      get 
      { 
       return JsonConvert.DeserializeObject<T>(base.Value); 
      } 
     } 
    } 

    public class UKPassport : ClaimValue 
    { 
     public const string Name = "UKPassport"; 

     private readonly PassportCode code; 
     private readonly int number; 
     private readonly DateTime expiryDate; 

     public UKPassport(PassportCode code, int number, DateTime expiryDate) 
     { 
      this.code = code; 
      this.number = number; 
      this.expiryDate = expiryDate; 
     } 

     public PassportCode Code { get { return this.code; } } 
     public int Number { get { return this.number; } } 
     public DateTime ExpiryDate { get { return this.expiryDate; } } 

     public override string ValueType() 
     { 
      return @"http://it.test/currentpassport"; 
     } 
    }  

public abstract class ClaimValue { 
    public abstract string ValueType(); 

    public override string ToString() 
    { 
     return JsonConvert.SerializeObject(this); 
    } 
} 
} 

Répondre

7

non prise en charge ni recommandé - allégations sont des paires clé/valeur - les garder aussi simple que possible.

Il y a un certain nombre de soutenir les classes .NET qui ne peuvent pas gérer ce que vous essayez d'atteindre (le SAM, CookieMiddleware etc) ..

voir aussi ici http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/

+0

J'ai lu quelques-unes de vos réponses et votre blog, mais je ne suis toujours pas sûr d'un scénario décrit ici http://stackoverflow.com/questions/39380623/complex-claims-in-jwt où dans le cadre de l'identité de l'utilisateur, nous voulons avoir ses rôles pour les différentes entreprises. Cela me semble une partie de l'information sur "qui est un utilisateur", mais il faudrait un JWT complexe que vous semblez ne pas aimer beaucoup. – iberodev

1

Le casting en GetPassport essaie de convertir du type de base Claim au type dérivé ComplexClaim<UKPassport> qui aboutira à null. Vous devez écrire un opérateur de cast pour convertir Claim-UKPassport

public static explicit operator UKPassport(Claim c) 
{ 
    return (c == null ? null:JsonConvert.DeserializeObject<UKPassport> (c.Value)); 
}  

et GetPassport sera

private static UKPassport GetPassport(this ClaimsIdentity identity, string passportType) 
{ 
    return (UKPassport)identity.Claims.FirstOrDefault<Claim>(c => c.Type == @"http://it.test/currentpassport"); 
} 
Questions connexes