2014-07-17 16 views
6

Sto sviluppando un'applicazione Web con token di trasporto Asp.Net 5 MVC, Owin e Oauth2 come tipo di autenticazione.Valori complessi dei reclami in .NET Framework con System.Security.Claims

seguito this guide che aggiunge una richiesta complessa personalizzata JSON serializzato a un'istanza di Microsoft.IdentityModel.Claims.ClaimsIdentity con successo, ho provato a replicare lo stesso esempio utilizzando il ClaimsIdentity sul System.Security.Claims namespace.

Purtroppo, sembra che l'aggiunta di un complexClaim all'istanza ClaimsIdentity, il derivato informazioni tipo di classe viene persa, e la richiesta viene memorizzato come System.Security.Claims.Claim.

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

Quando cerco di tornare la pretesa di identità, il cast a ad un ComplexClaim<UKPassport> risultati tipo in un valore nullo.

var passportClaim = identity.Claims.FirstOrDefault<Claim>(c=>c.Type == @"http://it.test/currentpassport") as ComplexClaim<UKPassport>; 

Lo stesso esempio funziona perfettamente con Microsoft.IdentityModel.Claims.

Eventuali suggerimenti?

Ecco il codice porting completo:

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

risposta

7

Questo non è supportato né consigliato - rivendicazioni sono coppie chiave/valore - tenerli più semplice possibile.

Ci sono un certo numero di classi di supporto in .NET che non possono gestire ciò che si sta cercando di ottenere (SAM, CookieMiddleware ecc) ..

vedi anche qui http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/

+0

ho letto alcune delle vostre risposte e il tuo blog, ma non sono ancora sicuro su uno scenario descritto qui http://stackoverflow.com/questions/39380623/complex-claims-in-jwt dove, come parte dell'identità dell'utente, vogliamo avere i suoi ruoli per diverse attività commerciali. Questo mi sembra parte delle informazioni su "chi è un utente", ma richiederebbe un JWT complesso che a quanto pare non ti piace molto .. – iberodev

1

Il cast in GetPassport tenta di convertire dal tipo base Claim al tipo derivato ComplexClaim<UKPassport> che si tradurrà in null. Hai bisogno di scrivere un operatore di cast convertire da Claim a UKPassport

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

e GetPassport sarà

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