使用System.Security.Claims实现.net框架中的复杂索赔值
本文关键字:复杂 框架 Security System Claims 实现 net 使用 | 更新日期: 2023-09-27 18:13:20
我正在开发一个web应用程序与Asp。. Net 5 MVC, Owin和Oauth2承载令牌作为验证类型。
按照这个成功地将自定义复杂索赔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>
类型会导致null值。
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, cookiemidleware等).
参见此处http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/
GetPassport
中的强制转换试图从基类型Claim
转换为派生类型ComplexClaim<UKPassport>
,这将导致null。您需要编写一个强制转换操作符来将Claim
转换为UKPassport
public static explicit operator UKPassport(Claim c)
{
return (c == null ? null:JsonConvert.DeserializeObject<UKPassport> (c.Value));
}
和GetPassport
将是
private static UKPassport GetPassport(this ClaimsIdentity identity, string passportType)
{
return (UKPassport)identity.Claims.FirstOrDefault<Claim>(c => c.Type == @"http://it.test/currentpassport");
}