使用Owin中间件添加声明

使用Owin中间件添加声明

本文介绍了使用Owin中间件添加声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Owin中间件实现是否可以在执行Web API控制器之前添加声明?

Is it possible with an Owin Middleware implementation to add claims prior to the execution of a Web API controller?

创建了OwinMiddleware实现并添加了身份:

Created an OwinMiddleware implementation and added an identity:

 var id = new ClaimsIdentity();
 id.AddClaim(new Claim("Whatever", "is possible"));
 context.Authentication.User.AddIdentity(id);

 await Next.Invoke(context);

但是,即使这个 Invoke 方法调用也不会更新身份(只是内部声明数组).当然,控制器在执行时也永远不会获得新的虚拟索赔.

However, even this Invoke method call the identities are not updated (just the internal claims array). And the controller when executed of course never gets the new dummy claim.

想法?

推荐答案

已经有一个可以提供声明扩展的类ClaimsAuthenticationManager,您可以对其进行扩展,以便处理特定于域的声明,例如...

There's already a class that can provide claims enrichment ClaimsAuthenticationManager, which you can extend so it handles your domain-specific claims, for example...

public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager
{
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (!incomingPrincipal.Identity.IsAuthenticated)
        {
            return base.Authenticate(resourceName, incomingPrincipal);
        }

        return AddApplicationClaims(incomingPrincipal);
    }

    private ClaimsPrincipal AddApplicationClaims(ClaimsPrincipal principal)
    {
        // TODO: Add custom claims here based on current principal.

        return principal;
    }
}

下一个任务是提供适当的中间件来调用它.对于我的项目,我编写了以下课程...

Next task is to provide appropriate middleware to invoke this. For my projects I've written the following classes...

/// <summary>
/// Middleware component to apply claims transformation to current context
/// </summary>
public class ClaimsTransformationMiddleware
{
    private readonly Func<IDictionary<string, object>, Task> next;
    private readonly IServiceProvider serviceProvider;

    public ClaimsTransformationMiddleware(Func<IDictionary<string, object>, Task> next, IServiceProvider serviceProvider)
    {
        this.next = next;
        this.serviceProvider = serviceProvider;
    }

    public async Task Invoke(IDictionary<string, object> env)
    {
        // Use Katana's OWIN abstractions
        var context = new OwinContext(env);

        if (context.Authentication != null && context.Authentication.User != null)
        {
            var manager = serviceProvider.GetService<ClaimsAuthenticationManager>();
            context.Authentication.User = manager.Authenticate(context.Request.Uri.AbsoluteUri, context.Authentication.User);
        }

        await next(env);
    }
}

然后是接线扩展...

And then a wiring extension...

public static class AppBuilderExtensions
{
    /// <summary>
    /// Add claims transformation using <see cref="ClaimsTransformationMiddleware" /> any depdendency resolution is done via IoC
    /// </summary>
    /// <param name="app"></param>
    /// <param name="serviceProvider"></param>
    /// <returns></returns>
    public static IAppBuilder UseClaimsTransformation(this IAppBuilder app, IServiceProvider serviceProvider)
    {
        app.Use<ClaimsTransformationMiddleware>(serviceProvider);

        return app;
    }
}

我知道这是服务定位器的反模式,但是使用IServiceProvider是容器中立的,并且似乎是将依赖项放入Owin中间件的公认方法.

I know this is service locator anti-pattern but using IServiceProvider is container neutral and seems to be the accepted way of putting dependencies into Owin middleware.

最后,您需要在Startup中进行连接,下面的示例假定Unity并注册/公开了IServiceLocator属性...

Last you need to wire this up in your Startup, example below presumes Unity and registering/exposing a IServiceLocator property...

// Owin config
app.UseClaimsTransformation(UnityConfig.ServiceLocator);

这篇关于使用Owin中间件添加声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 05:41