c# - 具有 System.Security.Claims 的 .NET Framework 中的复杂声明值

标签 c# asp.net-mvc-5 wif owin claims-based-identity

我正在开发一个使用 Asp.Net 5 MVC、Owin 和 Oauth2 不记名 token 作为身份验证类型的网络应用。

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/

相关文章:

federated-identity - 只有 7 个声明的大型 FedAuth Cookie (FedAuth4)

c# - 为什么枚举需要显式转换为 int 类型?

c# - 使用具有复杂类型的设置

c# - visual studio 在处理异常时中断

asp.net - 如何自定义 UseExternalSignInCookie?

c# - 使用 .NET WebAPI 进行服务器端验证

azure - 如何使用 Windows Azure 访问控制 "pre-authenticate"另一个用户?

silverlight - 如何将浏览器内 silverlight 客户端连接到 ACS - Azure - WIF - Entity Framework (公共(public)和私有(private)数据库模型)

c# - 在 VB.NET 或 C# 中使用 itextsharp dll 阅读 PDF 内容

c# - 默认情况下路由到 Index 之外的另一个操作