简体   繁体   English

Asp .net Core 3.1 使用多个 AuthenticationScheme 转换 ClaimsIdentity

[英]Asp .net Core 3.1 transforming ClaimsIdentity with multiple AuthenticationScheme

I've faced a problem while implementing a couple of authorization schemes in ASP.Net Core application.在 ASP.Net Core 应用程序中实现几个授权方案时,我遇到了一个问题。 Lets say they are declared like this in Startup.cs可以说它们在 Startup.cs 中是这样声明的

public void ConfigureServices(IServiceCollection services)
{
      AuthenticationBuilder builder = services
                .AddAuthentication()
                .AddBasicAuthentication(o => { o.Realm = "MyRealm"; })
                .AddApiKeyAuthentication()
                .AddBearerToken(opt => { });
}

Each of these schemes provide its own implementation of AuthenticationHandler returning ClaimsIdentity if succeeded.这些方案中的每一个都提供了自己的AuthenticationHandler实现,如果成功则返回ClaimsIdentity But in each case the structure of claims are incosistent, ie ApiKeyAuthentication may return ClaimsIdentity with business-sensitive data stored in claim "api_service" while BearerTokenScheme will store it in a claim "sub", and I dont have control over this.但在每种情况下,声明的结构都是不一致的,即 ApiKeyAuthentication 可能会返回ClaimsIdentity以及存储在声明“api_service”中的业务敏感数据,而 BearerTokenScheme 会将其存储在声明“sub”中,而我无法控制这一点。 So if I would like to use this information in a controller to associate some process with a service which have called my api method, I have to implement some complicated logic that would analyze current ClaimsIdentity , its auth scheme and set of claims.因此,如果我想在 controller 中使用此信息来将某些进程与调用了我的 api 方法的服务相关联,我必须实现一些复杂的逻辑来分析当前的ClaimsIdentity 、其身份验证方案和声明集。 Instead I would like to implement some sort of tranformation of ClaimsIdentity into MyServiceClaimsIdentity which would expose claims in a handy way so I can utilize them easily in my Controllers code:相反,我想实现某种将 ClaimsIdentity 转换为MyServiceClaimsIdentity的方式,这将以方便的方式公开声明,以便我可以在控制器代码中轻松使用它们:

public class MyServiceClaimsIdentity: IIdentity
{
    private readonly ClaimsIdentity innerIdentity;
    public Guid? UserId {get; }
    public string UserName {get; }
    public string ServiceName {get; }

    public MyServiceClaimsIdentity(ClaimsIdentity identity)
    {
        this.innerIdentity = identity;
        TransformClaimsIntoProperties();
    }

    private void TransformClaimsIntoProperties()
    {
        ......
    }
}

I've tried to implement some sort of "transformative" AuthenticationHandler which would produce MyServiceClaimsIdentity after all other handlers would produce their ClaimsIdentity.我试图实现某种“变革性” AuthenticationHandler ,它会在所有其他处理程序产生它们的 ClaimsIdentity 之后产生MyServiceClaimsIdentity

public class FinalAuthenticationHandler : AuthenticationHandler<FinalAuthenticationOptions>
    {
        public FinalAuthenticationHandler(
            IOptionsMonitor<FinalAuthenticationOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock)
            : base(options, logger, encoder, clock)
        {
        }

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!this.Context.User.Identity.IsAuthenticated)
            {
                return null;
            }

            var identity = new MyServiceClaimsIdentity(this.Context.User.Identity);
            var principal = new ClaimsPrincipal(identity);
            var ticket = new AuthenticationTicket(principal, this.Scheme.Name);
            return AuthenticateResult.Success(ticket);
        }
    }

Too bad at this point this.Context.User.Identity doesnt have any information of an user, so I'm confused where to put this tranformation logic or how would I get current ClaimsIdentity provided by other Handler in my FinalAuthenticationHandler .在这一点上太糟糕了this.Context.User.Identity没有用户的任何信息,所以我很困惑将这个转换逻辑放在哪里,或者我将如何在我的 FinalAuthenticationHandler 中获得其他 Handler 提供的当前ClaimsIdentity Any help would be appreciated.任何帮助,将不胜感激。

Implementing IClaimsTransformation and registering it as a Singleton did the job just fine实施 IClaimsTransformation 并将其注册为 Singleton 做得很好

internal sealed class ClaimsTransformation : IClaimsTransformation
    {
        private readonly IDictionary<string, IClaimsHandler> handlersMap;

        public ClaimsTransformation(IEnumerable<IClaimsHandler> handlers)
        {
            if (handlers == null)
            {
                throw new ArgumentNullException(nameof(handlers));
            }

            this.handlersMap = handlers.ToDictionary(t => t.SchemeName);
        }

        public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
        {
            if (!(principal.Identity is ClaimsIdentity claimsIdentity))
            {
                throw new InvalidOperationException($"Principal.Identity is of type {principal.Identity.GetType()}, expected ClaimsIdentity");
            }

            if (!this.handlersMap.TryGetValue(principal.Identity.AuthenticationType, out var handler))
            {
                throw new AuthenticationException($"Scheme of type {principal.Identity.AuthenticationType} is not supported");
            }

            var result = new ClaimsPrincipal(handler.Handle(claimsIdentity));
            return Task.FromResult(result);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET Core 3.1 Web API 中的“授权失败。AuthenticationScheme:AzureADJwtBearer 受到挑战” - 401 Unauthorized - "Authorization failed. AuthenticationScheme: AzureADJwtBearer was challenged" in ASP.NET Core 3.1 Web API - 401 Unauthorized 没有指定authenticationScheme,也没有找到DefaultChallengeScheme-ASP.NET Core 2.1 - No authenticationScheme was specified, and there was no DefaultChallengeScheme found - ASP.NET core 2.1 如何在ASP.NET Core中添加基于cookie的authenticationScheme? - How to add a cookie based authenticationScheme in ASP.NET Core? ASP.NET Core JWT 映射角色声明到 ClaimsIdentity - ASP.NET Core JWT mapping role claims to ClaimsIdentity 带有 Identity Core 和 Asp.net Core 3.1 的多重登录页面 - Multiple Login Page with Identity Core and Asp.net Core 3.1 尝试在.net核心中授权ClaimsIdentity - Trying to Authorize a ClaimsIdentity in .net core Asp.Net Core 3.1 多个依赖的自定义配置提供程序 - Asp.Net Core 3.1 Multiple dependent custom configuration providers ASP.NET Core 3.1,处理多个路由参数 - ASP.NET Core 3.1, handle multiple route parameters 在 ASP.NET Core 3.1 中使用多个身份验证方案? - Using multiple authentication schemes in ASP.NET Core 3.1? 在 ASP.NET Core 3.1 中为 Singleton 使用多项服务 - Use Multiple Services for Singleton in ASP.NET Core 3.1
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM