Return 在控制器上使用授权属性时的自定义响应

Return a custom response when using the Authorize Attribute on a controller

我刚刚实现了 Bearer 令牌,我已经将 Authorize 属性添加到我的控制器 class 并且工作正常。它看起来像这样:

[授权(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

我想做的是在服务器失败时创建一个更复杂的响应,而不是标准的 401。

我尝试了过滤器,但它们根本没有被调用。

有什么办法吗?

有自定义方案、自定义授权处理程序和 poof!

请注意,我在 ConfigureServices 中注入了处理程序:

services.AddAuthentication(options =>
            {
                options.DefaultScheme = ApiKeyAuthenticationOptions.DefaultScheme;
                options.DefaultAuthenticateScheme = ApiKeyAuthenticationOptions.DefaultScheme;
            })
                .AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(
                    ApiKeyAuthenticationOptions.DefaultScheme, o => { });

ApiKeyAuthenticationOptions

public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
    {
        public const string DefaultScheme = "API Key";
        public string Scheme => DefaultScheme;
        public string AuthenticationType = DefaultScheme;
        public const string HeaderKey = "X-Api-Key";
    }

ApiKeyAuthenticationHandler

    /// <summary>
    /// An Auth handler to handle authentication for a .NET Core project via Api keys.
    ///
    /// This helps to resolve dependency issues when utilises a non-conventional method.
    /// 
    /// </summary>
    public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
    {
        private readonly IServiceProvider _serviceProvider;

        public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options, ILoggerFactory logger, 
            UrlEncoder encoder, ISystemClock clock, IServiceProvider serviceProvider) 
            : base (options, logger, encoder, clock) 
        {
            _serviceProvider = serviceProvider;
        }

        protected override Task<AuthenticateResult> HandleAuthenticateAsync() 
        {
            var token = Request.Headers[ApiKeyAuthenticationOptions.HeaderKey];

            if (string.IsNullOrEmpty(token)) {
                return Task.FromResult (AuthenticateResult.Fail ("Token is null"));
            }

            var customRedisEvent = _serviceProvider.GetRequiredService<ICustomRedisEvent>();
            var isValidToken = customRedisEvent.Exists(token, RedisDatabases.ApiKeyUser);

            if (!isValidToken) {
                return Task.FromResult (AuthenticateResult.Fail ($"Invalid token {token}."));
            }

            var claims = new [] { new Claim ("token", token) };
            var identity = new ClaimsIdentity (claims, nameof (ApiKeyAuthenticationHandler));
            var ticket = new AuthenticationTicket (new ClaimsPrincipal (identity), Scheme.Name);
            return Task.FromResult (AuthenticateResult.Success (ticket));
        }
    }

关注处理程序class。除了我提供的示例代码之外,只需使用基本的 class 属性,例如 Response 来设置您的自定义 http 状态代码或您可能需要的任何内容!

这里是派生的 class 如果你需要的话。 https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.authenticationhandler-1?view=aspnetcore-3.1