[英]AuthorizeAttribute return Custom Value in ASP.net Core (Without Override)
I'm using ASP.NET Core 5.0 and making a REST API.我正在使用 ASP.NET Core 5.0 并制作 REST API。 I'm also using JWT tokens for authentication.
我还使用 JWT 令牌进行身份验证。
[Authorize]
public class LoginController : Controller
I have already added Authorization/Authentication middleware for JWT.我已经为 JWT 添加了授权/身份验证中间件。 How can I get AuthorizeAttribute to return a custom value if the authentication fails?
如果身份验证失败,如何让 AuthorizeAttribute 返回自定义值? Currently, it does this:
目前,它这样做:
Authorize Good token: nothing
Authorize Bad token: Return status 401/403
But I want it to do something like this where it returns 200 OK but with JSON response in the body, due to a need for consistency with my other responses and to be browser friendly但我希望它做这样的事情,它返回 200 OK 但在正文中有 JSON 响应,因为需要与我的其他响应保持一致并且对浏览器友好
Authorize Good token: nothing
Authorize Bad token: 200 OK <json>
Here is a template for what I would use for my JSON这是我将用于我的 JSON 的模板
{
succeeded: boolean
statusCode: number //http status code
response: array of strings //general info such as errors
}
Well, this is not so pretty (in terms of its placement), but should work fine:好吧,这不是很漂亮(就其位置而言),但应该可以正常工作:
.AddJwtBearer(options =>
{
// ...
options.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = ctx =>
ctx.Response.WriteAsJsonAsync(new
{
suceeded = false,
statusCode = yourStatusCode,
response = yourStringArray
})
};
// ...
}
Probably you're getting the gist of it.可能你已经掌握了它的要点。 You can set handlers for the various JWT token authentication events.
您可以为各种 JWT 令牌身份验证事件设置处理程序。
WriteAsJsonAsync()
automatically sets 200 status code and applicaton/json content-type. WriteAsJsonAsync()
自动设置 200 个状态码和 applicaton/json 内容类型。 But you can also write a string with WriteAsync()
, and set custom status code and content-type.但您也可以使用
WriteAsync()
编写字符串,并设置自定义状态代码和内容类型。
Here's another solution by trying to follow the pattern of cross-cutting concerns.这是尝试遵循横切关注点模式的另一种解决方案。 With this solution, of course we don't have to repeat the code for each authentication scheme.
有了这个解决方案,我们当然不必为每个身份验证方案重复代码。
First you cannot use IAuthorizationFilter
and IAsyncAuthorizationFilter
for this scenario because all the filters are executed in sequence and that sequence is not ensured to be in a determined order (usually at the step of policy combination, all AuthorizeFilter
s are appended after all other filters).首先,您不能在这种情况下使用
IAuthorizationFilter
和IAsyncAuthorizationFilter
,因为所有过滤器都按顺序执行,并且不能确保该顺序处于确定的顺序(通常在策略组合的步骤中,所有AuthorizeFilter
都附加在所有其他过滤器之后)。 So at the time your filter runs, the result may have not been set, you don't even know if the authorization is succeeded or failed.所以在你的过滤器运行的时候,可能还没有设置结果,你甚至不知道授权是成功还是失败。 You also cannot use
IResultFilter
and IAsyncResultFilter
because in case of some Result
is set after an authorization filter runs, the result filters will not be run.您也不能使用
IResultFilter
和IAsyncResultFilter
,因为如果在授权过滤器运行后设置了某些Result
,结果过滤器将不会运行。
Luckily we have one kind of filter that always runs in that case.幸运的是,我们有一种始终在这种情况下运行的过滤器。 That is
IAlwaysRunResultFilter
and IAsyncAlwaysRunResultFilter
.那就是
IAlwaysRunResultFilter
和IAsyncAlwaysRunResultFilter
。 So you can add one filter of that kind and override the result, something like this:因此,您可以添加一个此类过滤器并覆盖结果,如下所示:
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();
}
}
In the ForbidResult
(if set), you have access to a list of authentication schemes (if empty, the default scheme has been used), which may be helpful.在
ForbidResult
(如果设置)中,您可以访问身份验证方案列表(如果为空,则使用默认方案),这可能会有所帮助。 Note that the ForbidResult
may be set by one of the AuthorizeFilter
or one custom filter of yours.请注意,
ForbidResult
可能由AuthorizeFilter
之一或您的一个自定义过滤器设置。 However if your custom filter sets some result of a different type, the code above has no knowledge about that and may not easily know how to handle it.但是,如果您的自定义过滤器设置了一些不同类型的结果,则上面的代码对此一无所知,并且可能不容易知道如何处理它。 The good practice here is always use
ForbidResult
if you write other custom authorization filters which join in authorizing the request.如果您编写其他加入授权请求的自定义授权过滤器,这里的良好做法是始终使用
ForbidResult
。
Finally, if you use authorization middleware (introduced as a separate middleware since asp.net core 3.0
), I doubt that you can implement an IAuthorizationMiddlewareResultHandler
to intercept & override the result there.最后,如果您使用授权中间件(自
asp.net core 3.0
起作为单独的中间件引入),我怀疑您是否可以实现IAuthorizationMiddlewareResultHandler
来拦截并覆盖那里的结果。 I however did not test this way (and have never tried it yet).但是,我没有以这种方式进行测试(也从未尝试过)。 But I include it in here for you to try it yourself (it would be nice if you let me know the result you tried, working or not):
但是我将它包含在此处供您自己尝试(如果您让我知道您尝试的结果,无论是否有效,那就太好了):
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.
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.