本文介绍了如何在GRPC中将System.Security.Claims.Claimsain定义为请求参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在.Net代码下使用GRPC构建授权服务。为此,我需要将System.Security.Claims.ClaimsMaster对象作为请求参数从调用方传递到服务器,以便服务器可以使用它来授权调用方。但我不知道该怎么做--我怎么能为一个标准库的类定义一个.proto。我应该做什么?

推荐答案

我也在做同样的事情,使用的是协议buf-net GRPC库。由于许多Identity/Security类(如果您正在使用它们)来自Microsoft,您将需要公开它们的成员以进行序列化;您可以使用:

RuntimeTypeModel.Default.Add(typeof(SignInResult), false).Add(
            nameof(SignInResult.Succeeded),
            nameof(SignInResult.IsLockedOut),
            nameof(SignInResult.IsNotAllowed),
            nameof(SignInResult.RequiresTwoFactor)
        );

并列出需要通过GRPC公开的成员。至于ClaimsMaster,具体地说,这就是我目前正在尝试实现的。对于声明,我使用了一个代理类:

RuntimeTypeModel.Default.Add(typeof(Claim), true).SetSurrogate(typeof(ClaimSurrogate));

public class ClaimSurrogate
{
    [DataMember, ProtoMember(1)]
    public string Type { get; set; }
    [DataMember, ProtoMember(2)]
    public ClaimsIdentity Subject { get; set; }
    [DataMember, ProtoMember(3)]
    public IDictionary<string, string> Properties { get; set; }
    [DataMember, ProtoMember(4)]
    public string OriginalIssuer { get; set; }
    [DataMember, ProtoMember(5)]
    public string Issuer { get; set; }
    [DataMember, ProtoMember(6)]
    public string ValueType { get; set; }
    [DataMember, ProtoMember(7)]
    public string Value { get; set; }

    public static implicit operator ClaimSurrogate(Claim claim)
    {
        if (claim == null)
            return null;
        return new ClaimSurrogate()
        {
            Type = claim.Type,
            Subject = claim.Subject,
            Properties = claim.Properties,
            OriginalIssuer = claim.OriginalIssuer,
            Issuer = claim.Issuer,
            ValueType = claim.ValueType,
            Value = claim.Value
        };
    }

    public static implicit operator Claim(ClaimSurrogate surrogate)
    {
        if (surrogate == null)
            return null;
        return new Claim(surrogate.Type, surrogate.Value, surrogate.ValueType, surrogate.Issuer, surrogate.OriginalIssuer, surrogate.Subject);
    }

}

我假设Claimsmain可以用同样的方法来完成,但是,我对它有麻烦。这就是我对你的问题的理解。实际上,通过尝试提供答案...从字面上讲,我刚刚意识到我忽略了什么,我还需要为ClaimsIdentity设置一个代理

到目前为止,我需要具有get的"第三方"类的代理;只需要属性。Claimsain具有这些类型的属性,ClaimsIdentity也具有这些类型的属性(正如ClaimsIdentity所声称的那样)。如果ClaimsIdentitySurrogate成功了,我会更新/评论

更新:

是的,这是可以做到的。ClaimsIdentity和IIdentity将需要类似上例的代理。这些类用作Claimsain中的成员/属性。ClaimsIdentity:您可以混合使用SetSurrogate和Add(nameof(...))因为它有GET ONLES和GET/SET(GET/SET在添加部分)。不要将执行元包含在ClaimsIdentity代理中,因为它会在服务的启动过程中创建一个永无止境的循环。如果您确实包含它,请确保它不是DataMember/Protomembers。和(私有)在代理运算符中设置它。索赔也是如此。

本质上,任何具有引用父类的成员的代理,或具有引用此父类型的代理的其他类型的代理,都将创建循环引用,并在启动时使服务出错。

Identity:这是一个简单的问题,只是RuntimeTypeModel.Default.Add(typeof(IIdentity),FALSE)。

最后(当我认为我已经完成了这个更新时,我发布了这个更新,但是,在所有UT测试和更改等之中,我发布得有点早;在对ClaimMaster代理类进行了破坏性更改之后)...

您将需要一个IIdentity伪类,它将在您的Claimain代理程序中使用,而不是IIdentity标识{get;set;}。此伪类应从IIdentity继承,例如

[DataContract]
public class IIdentityFraud : System.Security.Principal.IIdentity

和在您的代理的隐式运算符中:

IIdentityFraud identityfraud = null;
if (claimPrincipal.Identity != null)
{
     identityfraud = new IIdentityFraud(claimPrincipal.Identity.AuthenticationType, claimPrincipal.Identity.Name, claimPrincipal.Identity.IsAuthenticated);
}

更新(2021/05/11):

[DataContract]
    public class ClaimsPrincipalSurrogate
    {
        [DataMember, ProtoMember(1)]
        public IIdentityFraud Identity { get; set; }
        [DataMember, ProtoMember(2)]
        public IEnumerable<ClaimsIdentity> Identities { get; set; }
        [DataMember, ProtoMember(3)]
        public IEnumerable<Claim> Claims { get; set; }

        public static implicit operator ClaimsPrincipalSurrogate(ClaimsPrincipal claimPrincipal)
        {
            if (claimPrincipal == null)
            {
                return null;
            }
            else
            {
                IIdentityFraud identityfraud = null;
                if (claimPrincipal.Identity != null)
                {
                    identityfraud = new IIdentityFraud(claimPrincipal.Identity.AuthenticationType, claimPrincipal.Identity.Name, claimPrincipal.Identity.IsAuthenticated);
                }

                return new ClaimsPrincipalSurrogate()
                {
                    Identity = identityfraud, // (System.Security.Principal.IIdentity)identityfraud,
                    Identities = claimPrincipal.Identities,
                    Claims = claimPrincipal.Claims
                };
            }
        }

        public static implicit operator ClaimsPrincipal(ClaimsPrincipalSurrogate surrogate)
        {
            if (surrogate == null)
                return null;

            if (surrogate.Identities != null && surrogate.Identities.Any() == true)
            {
                return new ClaimsPrincipal(surrogate.Identities);
            }
            else if (surrogate.Identity != null)
            {
                return new ClaimsPrincipal(surrogate.Identity);
            }
            return new ClaimsPrincipal();
        }

    }

    [DataContract]
    public class ClaimsIdentitySurrogate
    {
        [DataMember, ProtoMember(1)]
        public string AuthenticationType { get; set; }
        [DataMember, ProtoMember(2)]
        public string Name { get; set; }
        //[DataMember, ProtoMember(3)]
        //public string Label { get; set; }
        [DataMember, ProtoMember(4)]
        public bool IsAuthenticated { get; set; }
        [DataMember, ProtoMember(5)]
        public IEnumerable<Claim> Claims { get; private set; }
        //[DataMember, ProtoMember(6)]
        //public object BootstrapContext { get; set; }
        //[DataMember, ProtoMember(7)]
        public ClaimsIdentity Actor { get; private set; }
        [DataMember, ProtoMember(8)]
        public string RoleClaimType { get; set; }
        [DataMember, ProtoMember(9)]
        public string NameClaimType { get; set; }

        public static implicit operator ClaimsIdentitySurrogate(ClaimsIdentity claimIdentity)
        {
            if (claimIdentity == null)
                return null;
            return new ClaimsIdentitySurrogate()
            {
                AuthenticationType = claimIdentity.AuthenticationType,
                Name = claimIdentity.Name,
                //Label = claimIdentity.Label,
                IsAuthenticated = claimIdentity.IsAuthenticated,
                Claims = claimIdentity.Claims,
                //BootstrapContext = claimIdentity.AuthenticationType,
                Actor = claimIdentity.Actor,
                RoleClaimType = claimIdentity.RoleClaimType,
                NameClaimType = claimIdentity.NameClaimType
            };
        }

        public static implicit operator ClaimsIdentity(ClaimsIdentitySurrogate surrogate)
        {
            if (surrogate == null)
            {
                return null;
            }

            if (surrogate.Claims?.Any() == true)
            {
                return new ClaimsIdentity(surrogate.Claims, surrogate.AuthenticationType);
            }
            else
            {
                return new ClaimsIdentity(surrogate.AuthenticationType, surrogate.NameClaimType, surrogate.RoleClaimType);
            }
        }
    }


[DataContract]
public class IIdentityFraud : System.Security.Principal.IIdentity
{
    [DataMember, ProtoMember(1)]
    public string AuthenticationType { get; private set; }
    [DataMember, ProtoMember(2)]
    public string Name { get; private set; }
    [DataMember, ProtoMember(3)]
    public bool IsAuthenticated { get; private set; }

    public IIdentityFraud() { }
    public IIdentityFraud(string authenticationType, string name, bool isAuthenticated)
    {
        this.AuthenticationType = authenticationType;
        this.Name = name;
        this.IsAuthenticated = isAuthenticated;
    }
}


[DataContract] //don't know if this is really needed. Too involved in testing out the rest of it and have yet to come back to this.
public class IIdentitySurrogate : System.Security.Principal.IIdentity
{
    [DataMember, ProtoMember(1)]
    public string AuthenticationType { get; set; }
    [DataMember, ProtoMember(2)]
    public string Name { get; set; }
    [DataMember, ProtoMember(3)]
    public bool IsAuthenticated { get; set; }

    public static implicit operator IIdentitySurrogate(IIdentityFraud iidentity)
    {
        if (iidentity == null)
            return null;
        return new IIdentitySurrogate()
        {
            AuthenticationType = iidentity.AuthenticationType,
            Name = iidentity.Name,
            IsAuthenticated = iidentity.IsAuthenticated
        };
    }

    public static implicit operator IIdentityFraud(IIdentitySurrogate surrogate)
    {
        if (surrogate == null)
            return null;

        return new IIdentityFraud(surrogate.AuthenticationType, surrogate.Name, surrogate.IsAuthenticated);
    }

}

在初创企业中执行的更多内容:

#region ClaimsIdentity
            RuntimeTypeModel.Default.Add(typeof(ClaimsIdentity), true).Add(
                nameof(ClaimsIdentity.Label),
                nameof(ClaimsIdentity.BootstrapContext),
                nameof(ClaimsIdentity.Actor)
            ).SetSurrogate(typeof(ClaimsIdentitySurrogate));
            #endregion ClaimsIdentity

            #region ClaimsPrincipal
            RuntimeTypeModel.Default.Add(typeof(ClaimsPrincipal), true).SetSurrogate(typeof(ClaimsPrincipalSurrogate));
            #endregion ClaimsPrincipal

            #region IIdentity
            RuntimeTypeModel.Default.Add(typeof(IIdentity), true);
            #endregion IIdentity

这篇关于如何在GRPC中将System.Security.Claims.Claimsain定义为请求参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 04:29