简体   繁体   English

AuthorizeAttribute 在 ASP.net 核心中返回自定义值(无覆盖)

[英]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
}

Note: I have already created a custom authentication policy.注意:我已经创建了自定义身份验证策略。 I just need it to return a unique value which I don't know how to do.我只需要它返回一个我不知道该怎么做的唯一值。

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).首先,您不能在这种情况下使用IAuthorizationFilterIAsyncAuthorizationFilter ,因为所有过滤器都按顺序执行,并且不能确保该顺序处于确定的顺序(通常在策略组合的步骤中,所有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.您也不能使用IResultFilterIAsyncResultFilter ,因为如果在授权过滤器运行后设置了某些Result ,结果过滤器将不会运行。

Luckily we have one kind of filter that always runs in that case.幸运的是,我们有一种始终在这种情况下运行的过滤器。 That is IAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter .那就是IAlwaysRunResultFilterIAsyncAlwaysRunResultFilter 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.

相关问题 如何在 ASP.NET Core 中创建自定义 AuthorizeAttribute? - How do you create a custom AuthorizeAttribute in ASP.NET Core? 将连接字符串传递给 asp.net core 中的自定义 AuthorizeAttribute - Pass connection string to custom AuthorizeAttribute in asp.net core Asp.Net Core:访问AuthorizeHandler中的自定义AuthorizeAttribute属性 - Asp.Net Core: Access custom AuthorizeAttribute property in AuthorizeHandler ASP.NET 内核 Web API 自定义 AuthorizeAttribute 问题 - ASP.NET Core Web API custom AuthorizeAttribute issue ASP.NET Core MVC 6中的AuthorizeAttribute重定向 - AuthorizeAttribute redirect in ASP.NET Core MVC 6 Web API的AuthorizeAttribute(ASP.NET Core 2) - AuthorizeAttribute for Web API (ASP.NET Core 2) 智能缓存,用于ASP.NET中的自定义AuthorizeAttribute - Smart caching for custom AuthorizeAttribute in ASP.NET 如何在ASP.NET Core中创建自定义策略AuthorizeAttribute? - How do you create a custom Policy AuthorizeAttribute in ASP.NET Core? 如何在ASP.NET Core中添加全局`AuthorizeFilter`或`AuthorizeAttribute`? - How to add global `AuthorizeFilter` or `AuthorizeAttribute` in ASP.NET Core? AuthorizeAttribute 不适用于 ASP.NET Core 3.1 中的端点路由 - AuthorizeAttribute not working with Endpoint Routing in ASP.NET Core 3.1
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM