从Owin WebApi2返回描述性401消息

时间:2015-11-05 16:55:48

标签: asp.net asp.net-web-api asp.net-web-api2 owin authorize-attribute

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

{"Message":"Authorization has been denied for this request."}

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

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;
    }
}

然后在我的控制器上使用它:

[MyAuthorizeAttribute(Roles = "Foo")]
public class MyController : ApiController
{
    ...
}

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

{"Description": "This is why you're unauthorized"}

但是,我没有看到如何确定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中间件确定请求未经授权的具体原因?

1 个答案:

答案 0 :(得分:0)

Haven没有弄清楚如何识别到期时间,也没有找出无效的受众等等,但我最终使用它来至少根据角色返回403

您可以使用上述问题中的示例自定义消息(&#34;您必须拥有角色X才能访问此操作...&#34;)。

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;
            }
        }
    }
}