【问题标题】:Claims Auth with OWIN Self Hosted WebApi使用 OWIN 自托管 WebApi 声明身份验证
【发布时间】:2014-02-20 10:59:49
【问题描述】:

我使用以下配置自托管 WebApi:

Visual Studio 2012 / .NET 4.0

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();

    // authentication
    config.MessageHandlers.Add(new Shield.PresharedKeyAuthorizer());

    // routing
    config.Routes.MapHttpRoute(
        name: "Default",
        routeTemplate: "{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    appBuilder.UseWebApi(config);
}

我有一个简单的测试设置,带有以下 DelegatingHandler 来创建声明并将其附加到当前线程。

public class PresharedKeyAuthorizer : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        var claims = new List<Claim>();
        claims.Add(new Claim(ClaimTypes.Name, "superstar"));

        var identity = new ClaimsIdentity(claims, "PresharedKey");
        var principal = new ClaimsPrincipal(identity);

        Thread.CurrentPrincipal = principal;
        if (HttpContext.Current != null)
            HttpContext.Current.User = principal;

        return base.SendAsync(request, cancellationToken);
    }
}

但是,当我点击标有Authorize 属性的ApiController 时,它无法识别身份验证。

[Authorize]
public class FilesController : ApiController
{
    public IEnumerable<string> Get()
    {
        return new string[] { "Secure File A", "Secure File B" };
    }
}

删除Authorize属性并设置断点,我可以看到RequestContext.Principal属性确实为null。该请求在没有Authorize 属性的情况下正常工作,所以我知道自托管的设置是正确的,但我必须在身份验证管道中遗漏一些东西。

为了让该声明与Authorize 属性相抵触,我缺少什么?

此相关答案在由 IIS 托管时似乎可以使用相同的方法:https://stackoverflow.com/a/14872968/118224

【问题讨论】:

    标签: c# authentication asp.net-web-api owin claims-based-identity


    【解决方案1】:

    在消息处理程序中,像这样设置主体。

    request.GetRequestContext().Principal = principal;
    

    不要使用

    Thread.CurrentPrincipal = principal;
    
    if (HttpContext.Current != null)
        HttpContext.Current.User = principal;
    

    更新

    自从我从事 .NET 4.0/2012/Web API OwinHttpRequestContext 设置 Thread.CurrentPrincipal 和 OWIN 上下文中的主体。通过使用request.GetRequestContext().Principal,这些详细信息对您隐藏。长话短说,我相信如果你知道如何在 OWIN 上下文中设置主体,这将起作用。不确定如何从 Web API 消息处理程序中做到这一点。您可以通过 OWIN 中间件做到这一点。

    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        config.Routes.MapHttpRoute("default", "api/{controller}/{id}");
    
        //config.MessageHandlers.Add(new PresharedKeyAuthorizer());
    
        app.Use((IOwinContext context, Func<Task> next) =>
        {
            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, "superstar"));
    
            var identity = new ClaimsIdentity(claims, "PresharedKey");
            var principal = new ClaimsPrincipal(identity);
    
            context.Request.User = principal;
            return next.Invoke();
        });
    
        app.UseWebApi(config);
    }
    

    【讨论】:

    • 这是否仅在 WebApi 2.0 中可用?我正在运行 .Net4.0/VS2012,我会将其添加到我的答案中。
    • 是的,但您不是已经在使用 Web API 2 了吗?我以为你在检查Principal HttpRequestContext
    • 正确,我使用的是 webapi2。我实际上在 Controller 上使用 AuthorizeAttribute,它应该检查我认为的当前线程主体。
    • [Authorize] 得到这样的委托人 - IPrincipal user = actionContext.ControllerContext.RequestContext.Principal;
    • 感谢您的第一个答案现在可以正常工作。我花了一些时间才意识到来自 WebApi 的 [Authorize] 属性与来自 System.Web 的 [Authorize] 具有不同的实现。我只需要引用正确的。为了可移植性,我将设置所有三个值,以便无论托管在何处都能正常工作。
    猜你喜欢
    • 1970-01-01
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 2014-08-19
    • 1970-01-01
    • 2018-01-28
    相关资源
    最近更新 更多