authentication - 如何在自定义 `AuthenticationHandler` 中的 `HandleAuthenticateAsync` 和 `HandleChallengeAsync` 之间传递对象?
问题描述
我无法找到正确的方法将对象从HandleAuthenticateAsync
我的自定义身份验证代码所在的位置传递到HandleChallengeAsync
回调,在那里我处理身份验证失败并设置响应状态代码和正文。
如果身份验证失败,我想返回一个 JSON 对象,该对象在响应正文中包含有关身份验证失败原因的一些信息。
在我的处理程序代码中,我想从方法中序列化一些results
值HandleChallengeAsync
:
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
public const string ApiKeyHeaderName = "X-API-KEY";
public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { }
// The authentication handler that gets call for every request (including `[AllowAnonymous]`
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
Request.Headers.TryGetValue(Options.ApiKeyHeaderName, out var apiKeyHeaderValues);
var key = apiKeyHeaderValues.FirstOrDefault();
var results = await new AuthenticateApiKeyQuery(key).Results();
if (results.HasErrors())
return AuthenticateResult.Fail("Useless message that doesn't go anywhere");
return Success(results.Value);
}
// the callback that gets called for any `[Authorize]` actions
override protected async Task HandleChallengeAsync(AuthenticationProperties properties)
{
var errors = new { }; // I want `errors` to come from the `result` object above
Context.Response.StatusCode = 401;
Context.Response.ContentType = "application/json";
var json = Newtonsoft.Json.JsonConvert.SerializeObject(errors);
await Context.Response.Body.WriteAsync(System.Text.Encoding.UTF8.GetBytes(json));
}
// Method that sent up the identity/claim etc
private AuthenticateResult Success(ApiKey apiKey)
{
var claims = new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, apiKey.ID.ToString()),
new Claim(ClaimTypes.Name, apiKey.Description),
};
var identity = new ClaimsIdentity(claims, Options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
var ticket = new AuthenticationTicket(principal, Options.AuthenticationScheme);
return AuthenticateResult.Success(ticket);
}
我最初的尝试是HandleAuthenticateAsync
设置 401 和响应正文的方法。这不起作用,因为身份验证处理程序也会为标记为 的操作运行[AllowAnonymous]
。结果是响应将是 401,并且是序列化的 JSON,而不是操作设置的状态和响应。而 ,HandleChallengeAsync
仅在身份验证失败且操作需要授权时调用。
这不是最容易导航的代码,但据我所知,PolicyEvalulator
调用AuthenticationHandler
然后调用我的 custom HandleAuthenticateAsync
。然后AuthenticateResult
我返回的被 吞没PolicyEvalulator
,所以我不能用它来保存任何值以供以后处理。我还没有弄清楚什么叫我的 custom HandleChallengeAsync
,但是到现在为止,AuthenticateResult
它已经被吞没了。
解决方案
我遇到了类似的问题,身份验证处理程序是瞬态范围的,您可以在自定义处理程序类中声明一个对象类型属性,该属性将在 HandleChallengeAsync 方法中可用。
推荐阅读
- mysql - 在 phpmyadmin 中创建存储过程的问题,列数 mysql.proc 不正确
- firefox - 如何获取由 Firefox 生成的转换后的 HTML 代码?
- javascript - “活动”类仅在使用页面扩展时设置
- python - 如何在数据框中以分钟/小时为单位读取时间以获取销售率?
- veins - 静脉 - BSM 消息
- c - 在函数之外更改静态变量的值
- vb.net - 以编程方式在 vb.net 中查找 Web 链接
- php - 摆脱存储库类中的 use Illuminate\Support\Facades\DB 语句
- .net-core - System.PlatformNotSupportedException:此平台不支持 System.Data.SqlClient
- php - PHP 和 HTML 结合时的 MAMP Bad Gateway