声明使用OWIN自托管WebApi进行身份验证

时间:2014-01-28 21:44:33

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

我使用以下配置自我托管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);
    }
}

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

[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

1 个答案:

答案 0 :(得分:17)

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

request.GetRequestContext().Principal = principal;

不要使用

Thread.CurrentPrincipal = principal;

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

<强>更新

自从我使用.NET 4.0 / 2012 / Web API&lt; 2以来,已经有一段时间了。所以,我无法回答。但是使用OWIN托管,必须在OWIN上下文中设置主体。 OwinHttpRequestContext在OWIN上下文中设置Thread.CurrentPrincipal和主体。使用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);
}
相关问题