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

Cha*_*own 13 c# authentication claims-based-identity asp.net-web-api owin

我通过以下配置自我托管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);
}
Run Code Online (Sandbox Code Playgroud)

我有一个简单的测试设置,使用以下内容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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

我错过了什么以允许该声明对该Authorize属性起作用?

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

Bad*_*dri 18

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

request.GetRequestContext().Principal = principal;
Run Code Online (Sandbox Code Playgroud)

不使用

Thread.CurrentPrincipal = principal;

if (HttpContext.Current != null)
    HttpContext.Current.User = principal;
Run Code Online (Sandbox Code Playgroud)

UPDATE

自从我使用.NET 4.0/2012/Web API <2以来已经有一段时间了.所以,我无法回答.但是使用OWIN托管,必须在OWIN上下文中设置主体.在OWIN上下文中OwinHttpRequestContext设置两者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);
}
Run Code Online (Sandbox Code Playgroud)