【问题标题】:Return a custom response when using the Authorize Attribute on a controller在控制器上使用授权属性时返回自定义响应
【发布时间】:2020-07-07 05:22:33
【问题描述】:

我刚刚实现了 Bearer 令牌,并且我已将 Authorize 属性添加到我的控制器类中,并且效果很好。它看起来像这样:

[授权(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

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

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

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

【问题讨论】:

    标签: rest .net-core asp.net-core-webapi bearer-token authorize-attribute


    【解决方案1】:

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

    请注意,我在 ConfigureServices 中注入了 Handler:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 2014-10-28
      相关资源
      最近更新 更多