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
我刚刚实现了 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