C# AuthorizeAttribute返回ASP.net Core中的自定义值(无覆盖)
我正在使用ASP.NETCore5.0并制作一个RESTAPI。 我还使用JWT令牌进行身份验证C# AuthorizeAttribute返回ASP.net Core中的自定义值(无覆盖),c#,asp.net-core,C#,Asp.net Core,我正在使用ASP.NETCore5.0并制作一个RESTAPI。 我还使用JWT令牌进行身份验证 [授权] 公共类登录控制器:控制器 我已经为JWT添加了授权/认证中间件。如果身份验证失败,如何让AuthorizeAttribute返回自定义值?目前,它是这样做的: Authorize Good token: nothing Authorize Bad token: Return status 401/403 但我希望它能像这样做,返回200 OK,但正文中有JSON响应,因为需要与我的其他
[授权]
公共类登录控制器:控制器
我已经为JWT添加了授权/认证中间件。如果身份验证失败,如何让AuthorizeAttribute返回自定义值?目前,它是这样做的:
Authorize Good token: nothing
Authorize Bad token: Return status 401/403
但我希望它能像这样做,返回200 OK,但正文中有JSON响应,因为需要与我的其他响应保持一致,并且对浏览器友好
Authorize Good token: nothing
Authorize Bad token: 200 OK <json>
注意:我已经创建了自定义身份验证策略。我只需要它返回一个我不知道怎么做的唯一值。好吧,这不是很漂亮(就其位置而言),但应该可以正常工作:
.AddJwtBearer(选项=>
{
// ...
options.Events=newjwtbearerevents()
{
OnAuthenticationFailed=ctx=>
ctx.Response.WriteAsJsonAsync(新的
{
成功=错误,
statusCode=您的状态代码,
response=yourStringArray
})
};
// ...
}
您可能已经了解了要点。您可以为各种JWT令牌身份验证事件设置处理程序。
WriteAsJsonAsync()
自动设置200个状态代码和applicaton/json内容类型。但您也可以使用WriteAsync()编写字符串
,并设置自定义状态代码和内容类型。这里是另一个解决方案,尝试遵循横切关注点的模式。使用此解决方案,我们当然不必为每个身份验证方案重复代码
首先,您不能在此场景中使用iaauthorizationfilter
和IAsyncAuthorizationFilter
,因为所有筛选器都是按顺序执行的,并且不能确保顺序是确定的(通常在策略组合步骤中,所有authorizationfilter
都附加在所有其他筛选器之后)。因此,在运行筛选器时,结果可能尚未设置,您甚至不知道授权是成功还是失败。您也不能使用IResultFilter
和IAsyncResultFilter
,因为如果在运行授权筛选器之后设置了一些result
,则结果筛选器将不被运行
幸运的是,我们有一种过滤器总是在这种情况下运行。那就是IAlwaysRunsultFilter
和IAsyncalwaysRunsultFilter
。因此,您可以添加一个此类过滤器并覆盖结果,如下所示:
public class CustomAsyncAlwaysRunResultFilterAttribute : Attribute, IAsyncAlwaysRunResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (context.HttpContext.Response.StatusCode == 403 ||
context.Result is ForbidResult)
{
//set the result of your choice
context.Result = new JsonResult(new { ... });
}
await next();
}
}
在result
(如果设置)中,您可以访问身份验证方案列表(如果为空,则使用默认方案),这可能会有所帮助。
请注意,禁止结果
可以由一个授权筛选器
或您的一个自定义筛选器设置。但是,如果您的自定义筛选器设置了不同类型的结果,则上面的代码对此一无所知,可能不容易知道如何处理。如果您rite加入授权请求的其他自定义授权筛选器
最后,如果您使用授权中间件(自asp.net core 3.0
以来作为一个单独的中间件引入),我怀疑您能否实现IAAuthorizationMiddleWareResultHandler
来拦截和覆盖那里的结果。但是,我没有用这种方法进行测试(而且从未尝试过).但我将其包含在这里,供您自己尝试(如果您告诉我您尝试的结果,无论是否有效,那将非常好):
我可以针对不同的策略做出不同的响应吗?或者不可以?啊,我想你的意思是作为一个交叉关注点。我现在在文档中读到“即使身份验证失败也会调用授权处理程序”,所以我认为这应该是可能的。但不幸的是,现在已经太晚了,所以我明天必须研究它(并编辑答案)。当然,希望同时有其他人会回答,或者也许你能让它工作。是的,它确实工作了。除了身份验证失败之外,这是一个挑战。它也适用于OnForbidden的自定义策略。但是,它不能在两个不同的自定义策略之间生成不同的响应,我现在对此很满意因为我只使用了一个。
public class CustomAsyncAlwaysRunResultFilterAttribute : Attribute, IAsyncAlwaysRunResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (context.HttpContext.Response.StatusCode == 403 ||
context.Result is ForbidResult)
{
//set the result of your choice
context.Result = new JsonResult(new { ... });
}
await next();
}
}
public class CustomAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler {
public Task HandleAsync (RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult){
//here you have access to the AuthorizationPolicy
//but note that the policy contains no name (as added in the configuration)
//it's kind of combined set of authentication schemes & handlers.
}
}