故事是关于什么的?
如果您认为在 ASP.NET Core 中管理身份验证意味着满足于一种方法,那么想象一下这样一个世界:您可以无缝处理多个身份验证方案,所有这些都在同一个应用程序中。突然之间,您可以毫不费力地支持不同的身份验证方法,如 JWT 令牌、自定义令牌,甚至 IdentityServer 配置。您知道如何在 .NET 8 中有效地实现这些不同的方案吗?如果您有兴趣构建一个强大而灵活的身份验证系统,您应该阅读本指南。
为什么使用多种身份验证方案?
在现代应用程序中,通常支持各种客户端和服务,每个客户端和服务都需要不同的身份验证机制。例如:
微服务通信:内部服务可能会使用 JWT 进行 API 到 API 的通信。
用户身份验证:外部用户可以通过第三方提供商或自定义令牌机制进行身份验证。
旧系统:与旧系统集成可能需要不同的身份验证协议。
我们可以利用 ASP.NET Core 的灵活性来设置多个身份验证方案,从而提供两全其美的效果,而不是强制所有客户端都遵循单一的身份验证方法。让我们深入了解如何使用 .NET 8 实现此目的。
在 .NET 8 中设置多个身份验证方案
在本教程中,我们将使用 ASP.NET Core 和 .NET 8 实现多个身份验证方案,包括针对不同标识服务器的 JWT 身份验证和自定义身份验证处理程序。这将允许我们处理来自不同来源的令牌,并支持用于令牌验证的自定义逻辑。
1. 配置身份验证方案
首先,我们将在 或专用服务扩展方法中设置身份验证服务。我们的目标是支持多个 JWT 令牌源,例如 和 ,以及用于专用令牌处理的自定义身份验证方案。Program.csIdentityServerAIdentityServerB
public static class DIExtension
{
public static void SetupAuthentication(this IServiceCollection services, IConfiguration config)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = config["IdentitySeverA:Audience"],
ValidIssuer = config["IdentitySeverA:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeyForIssuerA"))
};
})
.AddJwtBearer("Scheme_ServerB", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = config["IdentitySeverB:Audience"],
ValidIssuer = config["IdentitySeverB:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeyForIssuerB"))
};
})
.AddScheme<CustomAuthSchemeOptions, CustomAuthenticationHandler>("CustomToken", options => { });
}
}
2. 实现自定义身份验证处理程序
自定义身份验证处理程序将使我们能够执行更复杂的身份验证方案,例如针对数据库验证令牌。下面是如何创建自定义身份验证处理程序的示例。
public class CustomAuthenticationHandler : AuthenticationHandler<CustomAuthSchemeOptions>
{
private readonly ITokenRepository _tokenRepository;
public CustomAuthenticationHandler(
IOptionsMonitor<CustomAuthSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
ITokenRepository tokenRepository)
: base(options, logger, encoder, clock)
{
_tokenRepository = tokenRepository;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue("Authorization", out var customToken))
return AuthenticateResult.Fail("No token provided");
var token = customToken.ToString().GetAccessToken();
var dbToken = await _tokenRepository.GetAsync(token);
if (dbToken == null)
return AuthenticateResult.Fail("Invalid token");
var claims = new ClaimsIdentity(nameof(CustomAuthenticationHandler));
claims.AddClaim(new Claim("userId", dbToken.UserId));
var ticket = new AuthenticationTicket(new ClaimsPrincipal(claims), Scheme.Name);
return AuthenticateResult.Success(ticket);
}
}
3. 使用策略方案将请求路由到相应的身份验证处理程序
该方法允许您根据传入请求动态选择要使用的身份验证方案。以下是我们如何配置它。AddPolicyScheme
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddPolicyScheme(JwtBearerDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme, options =>
{
options.ForwardDefaultSelector = context =>
{
var token = context.Request.Headers[HeaderNames.Authorization].ToString().GetAccessToken();
var jwtHandler = new JwtSecurityTokenHandler();
if (jwtHandler.CanReadToken(token))
{
var issuer = jwtHandler.ReadJwtToken(token).Issuer;
return issuer == config["IdentitySeverA:Issuer"] ? "Scheme_ServerA" : "Scheme_ServerB";
}
return "CustomToken";
};
});
控制器示例:使用多个身份验证方案
在控制器中,您可以指定应为每个终端节点使用哪种身份验证方案。
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet("serverA")]
[Authorize]
public IActionResult GetServerAData()
{
// Fetch data secured by IdentityServerA token
return Ok("Data from Server A");
}
[HttpGet("serverB")]
[Authorize(AuthenticationSchemes = "Scheme_ServerB")]
public IActionResult GetServerBData()
{
// Fetch data secured by IdentityServerB token
return Ok("Data from Server B");
}
[HttpGet("custom")]
[Authorize(AuthenticationSchemes = "CustomToken")]
public IActionResult GetCustomTokenData()
{
// Fetch data secured by custom token
return Ok("Data from Custom Token");
}
}
测试身份验证流程
要验证设置,请执行以下操作:
使用 Swagger:可以使用 Swagger 配置应用程序以支持基于令牌的身份验证测试。
Postman 或 HTTP 客户端:使用不同的令牌发送请求,以查看策略方案如何路由到正确的身份验证处理程序。
通过使用 .NET 8 在 ASP.NET Core 中设置多个身份验证方案,可以轻松管理各种客户端方案的不同身份验证要求。这种方法不仅提高了身份验证基础设施的灵活性,还使您的应用程序能够适应未来需求,以便根据需要集成其他身份验证方法。
点击下方卡片关注DotNet NB
一起交流学习
▲ 点击上方卡片关注DotNet NB,一起交流学习
请在公众号后台