.NET Framework中的复杂声明值与System.Security.Claims
我正在使用Asp.Net 5 MVC,Owin和Oauth2 bearer token作为auth类型开发一个Web应用程序。
按照本指南将Json序列化的自定义复杂声明成功添加到Microsoft.IdentityModel.Claims.ClaimsIdentity
实例,我尝试使用System.Security.Claims
命名空间上的ClaimsIdentity复制相同的示例。
不幸的是,似乎将一个complexClaim
添加到ClaimsIdentity
实例,派生的类类型信息将丢失,并且声明将存储为System.Security.Claims.Claim
。
var complexClaim = new ComplexClaim(@"http://it.test/currentpassport", passport); var claims = new List() { complexClaim }; identity.AddClaims(claims);
当我尝试从身份中取回声明时,将其转换为ComplexClaim
Type会产生空值。
var passportClaim = identity.Claims.FirstOrDefault(c=>c.Type == @"http://it.test/currentpassport") as ComplexClaim;
相同的示例使用Microsoft.IdentityModel.Claims
完美运行。
任何提示?
这是完整的移植代码:
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(@"http://it.test/currentpassport", passport); var claims = new List() { 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(c=>c.Type == @"http://it.test/currentpassport") as ComplexClaim; return passportClaim.Value; } } public enum PassportCode { GBR, GBD, GBO, GBS, GBP, GBN } public class ComplexClaim : 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(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); } } }
这不是支持也不是建议 – 声明是键/值对 – 保持它们尽可能简单。
.NET中有许多支持类无法处理您要实现的目标(SAM,CookieMiddleware等)。
另见http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/
GetPassport
中的GetPassport
转换尝试从基类型Claim
转换为派生类型ComplexClaim
,这将导致null。 您需要编写一个UKPassport
转换操作符来将Claim
转换为UKPassport
public static explicit operator UKPassport(Claim c) { return (c == null ? null:JsonConvert.DeserializeObject (c.Value)); }
和GetPassport
将是
private static UKPassport GetPassport(this ClaimsIdentity identity, string passportType) { return (UKPassport)identity.Claims.FirstOrDefault(c => c.Type == @"http://it.test/currentpassport"); }
- ASP.NET身份确认电子邮件是纯文本而不是HTML
- 如何将Autofac与WepApi 2和Owin集成?
- 基于Http Header值的ASP.NET MVC5 / 6路由
- SignInManager,它是什么以及如何使用?
- mvc 5表中的SelectList,DropDownList为空值
- 如何在MVC5项目中使用Json.NET进行JSON模型绑定?
- OWIN OpenID提供程序 – GetExternalLoginInfo()返回null
- 如何在unit testing中模拟控制器上下文,以便我对字符串函数的部分视图有效?
- Google的间歇性ASP.NET oAuth问题,AuthenticationManager.GetExternalIdentityAsync返回null