不幸的是我找不到任何可以帮助我解决这个问题的东西。
通常API使用OIDC来处理身份验证,所以我们.AddAuthentication.AddJwtBearer默认使用普通的。这很好用,但我们还需要能够有另一种身份验证方式来提供用户身份,因为令牌并不总是可用。假设它是某个 ApiKey,其中包含给定 ApiKey 的用户字典。
尽管如此,我还是希望 JWT 令牌比另一层具有优先级,因为它只是更强的身份验证。所以它会是这样的:
目前,我们有多个支持令牌或 ApiKey(不同属性)场景的控制器端点,但是当控制器和端点数量增加时,复制所有内容可能会非常痛苦。
我尝试附加到一些JwtBearerEvents标头并检查那里的标头,这样如果我发现我们没有可用的令牌,我可以手动完成身份验证,例如:
OnMessageReceived = async context =>
{
if (!context.Request.Headers.ContainsKey("Authorization")
&& context.Request.Headers.ContainsKey("ApiKey"))
{
// some logic to check that ApiKey
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(
new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, "ApiKeyUser")
}));
context.Success();
}
await Task.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,中间件无论如何都坚持检查令牌并返回 401,因此这很可能不是解决该问题的有效方法。
我找到了一种方法,所以我将其留在这里。您只需AddPolicyScheme通过名称调用来添加将使用不同处理程序的选择器。
例如:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = smartAuthenticationScheme; // just some string
options.DefaultChallengeScheme = smartAuthenticationScheme;
options.DefaultScheme = smartAuthenticationScheme;
})
.AddPolicyScheme(smartAuthenticationScheme, "Token / Custom", options =>
{
options.ForwardDefaultSelector = context =>
{
var header = (string)context.Request.Headers["Authorization"];
if (header == null || string.IsNullOrEmpty(header))
return undefinedAuthenticationScheme;
if (header.StartsWith("Bearer"))
return bearerAuthenticationScheme; // it's just JwtBearerDefaults.AuthenticationScheme
if (header.StartsWith("Custom"))
return customAuthenticationScheme;
return undefinedAuthenticationScheme;
};
})
.AddJwt(bearerAuthenticationScheme, configuration)
.AddCustom(customAuthenticationScheme)
.AddUndefined(undefinedAuthenticationScheme);
Run Code Online (Sandbox Code Playgroud)
这样我们的中间件将查看 Authorization 标头的内容并调用以给定名称注册的 AuthenticationHandler 。当 Authorization header 的内容既不匹配 Jwt 也不匹配 Custom AuthorizationHandler 时,UndefinedHandler 的存在只是为了提供 401 响应。
| 归档时间: |
|
| 查看次数: |
1477 次 |
| 最近记录: |