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

问题描述 投票:0回答:1

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

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

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

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

任何想法如何做到这一点?

rest .net-core asp.net-core-webapi bearer-token authorize-attribute
1个回答
0
投票

具有自定义方案,自定义授权处理程序和po!

注意,我将处理程序注入了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.
    /// https://stackoverflow.com/questions/47324129/no-authenticationscheme-was-specified-and-there-was-no-defaultchallengescheme-f
    /// </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));
        }
    }

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

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

© www.soinside.com 2019 - 2024. All rights reserved.