我正在使用Asp.Net 5 MVC,Owin和Oauth2承载 token 作为身份验证类型开发Web应用程序。
在this guide成功添加了将自定义复杂声明Json序列化到Microsoft.IdentityModel.Claims.ClaimsIdentity
实例之后,我尝试使用System.Security.Claims
命名空间上的ClaimsIdentity复制相同的示例。
不幸的是,似乎在complexClaim
实例中添加了ClaimsIdentity
,丢失了派生的类类型信息,并且将声明存储为System.Security.Claims.Claim
。
var complexClaim = new ComplexClaim<UKPassport>(@"http://it.test/currentpassport", passport);
var claims = new List<Claim>() { complexClaim };
identity.AddClaims(claims);
当我尝试从身份取回声明时,将其强制转换为
ComplexClaim<UKPassport>
类型会导致返回空值。var passportClaim = identity.Claims.FirstOrDefault<Claim>(c=>c.Type == @"http://it.test/currentpassport") as ComplexClaim<UKPassport>;
使用
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<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);
}
}
}
最佳答案
不支持也不建议这样做-声明是键/值对-使其尽可能简单。
.NET中有许多支持类无法处理您要实现的目标(SAM,CookieMiddleware等)。
在这里也可以看到
http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/
关于c# - 带有System.Security.Claims的.NET Framework中的复杂声明值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24813709/