C# 我如何拥有多个身份验证方法,而只有一个方法必须成功?
不幸的是,在这件事上,我找不到任何对我有帮助的东西 通常API使用OIDC来处理身份验证,因此我们将普通C# 我如何拥有多个身份验证方法,而只有一个方法必须成功?,c#,asp.net-core,C#,Asp.net Core,不幸的是,在这件事上,我找不到任何对我有帮助的东西 通常API使用OIDC来处理身份验证,因此我们将普通.AddAuthentication.AddJwtBearer用作默认值。这很好,但我们还需要能够有另一种身份验证方式来提供用户身份,因为令牌并不总是可用的。假设它是一个ApiKey,其中包含给定ApiKey的用户字典 尽管如此,我还是希望JWT令牌优先于另一层,因为它只是一种更强的身份验证。所以它应该是这样的: 我们收到请求 若我们看到授权头,那个么这意味着请求提供了令牌——我们想要验证那个
.AddAuthentication.AddJwtBearer
用作默认值。这很好,但我们还需要能够有另一种身份验证方式来提供用户身份,因为令牌并不总是可用的。假设它是一个ApiKey,其中包含给定ApiKey的用户字典
尽管如此,我还是希望JWT令牌优先于另一层,因为它只是一种更强的身份验证。所以它应该是这样的:
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;
}
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);
不幸的是,中间件仍然坚持检查令牌并返回401,所以这很可能不是解决该问题的有效方法。我找到了一种方法,所以我将把它留在这里。您只需使用
AddPolicyScheme
添加选择器,该选择器将通过按名称调用来使用不同的处理程序
例如:
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;
}
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);
这样,我们的中间件将查看授权头的内容,并调用在给定名称下注册的AuthenticationHandler。当授权头的内容既不匹配Jwt也不匹配自定义AuthorizationHandler时,UndefinedHandler仅为401响应提供服务