从Owin WebApi2返回描述性401消息

Gre*_*reg 8 asp.net authorize-attribute asp.net-web-api owin asp.net-web-api2

我有一个使用owin运行的asp.net 4.5 web api.无论何时发出未经授权的请求,它都会按预期返回401以及以下响应:

{"Message":"Authorization has been denied for this request."}
Run Code Online (Sandbox Code Playgroud)

我想在此响应中添加其他详细信息(过期令牌,无效角色等等),并[AuthorizeAttribute]根据此SO帖子实施自定义.

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        var response = actionContext.Request.CreateResponse<MyError>
            (new MyError() { Description = "This is why you're unauthorized" });
        response.StatusCode = HttpStatusCode.Unauthorized;
        actionContext.Response = response;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的控制器上使用它,如下所示:

[MyAuthorizeAttribute(Roles = "Foo")]
public class MyController : ApiController
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

返回401,并按预期返回以下响应:

{"Description": "This is why you're unauthorized"}
Run Code Online (Sandbox Code Playgroud)

不过,我看不出如何确定请求来自于未授权的原因HttpActionContext传递给MyAuthorizeAttribute.HandleUnauthorizedRequest.例如,当我在本地进行调试并使用过期令牌发出请求时,它会抛出一个SecurityTokenExpiredException解释IDX10223: Lifetime validation failed. The token is expired. ValidTo: '...' Current time: '...'.或者无效的受众,它会抛出一个SecurityTokenInvalidAudienceException解释Message=IDX10214: Audience validation failed. Audiences: '...'. Did not match: validationParameters.ValidAudience: 'null' or validationParameters.ValidAudiences: '...'.我已经在我设置了几个断点Startup.cs但是之前甚至无法捕获其中一个例外他们被扔了.

如何使用owin中间件确定请求未经授权的具体原因?

Gre*_*reg 0

还没有弄清楚如何识别过期或无效受众等,但我最终使用它至少403根据角色返回 s 。

您可以使用我上面问题中的示例自定义消息(“您必须具有角色 X 才能访问此操作...”)。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);

        if (actionContext.RequestContext.Principal != null && 
            actionContext.RequestContext.Principal.Identity.IsAuthenticated && 
            Roles != null)
        {
            if (!Roles.Split(',').Any(x => 
                actionContext.RequestContext.Principal.IsInRole(x.Trim())))
            {
                actionContext.Response.StatusCode = HttpStatusCode.Forbidden;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)