如果您认为在 ASP.NET Core 中管理身份验证意味着满足于一种方法,那么想象一下这样一个世界:您可以无缝处理多个身份验证方案,所有这些都在同一个应用程序中。突然之间,您可以毫不费力地支持不同的身份验证方法,如 JWT 令牌、自定义令牌,甚至 IdentityServer 配置。您知道如何在 .NET 8 中有效地实现这些不同的方案吗?如果您有兴趣构建一个强大而灵活的身份验证系统,您应该阅读本指南。
在现代应用程序中,通常支持各种客户端和服务,每个客户端和服务都需要不同的身份验证机制。例如:
我们可以利用 ASP.NET Core 的灵活性来设置多个身份验证方案,从而提供两全其美的效果,而不是强制所有客户端都遵循单一的身份验证方法。让我们深入了解如何使用 .NET 8 实现此目的。
在本教程中,我们将使用 ASP.NET Core 和 .NET 8 实现多个身份验证方案,包括针对不同标识服务器的 JWT 身份验证和自定义身份验证处理程序。这将允许我们处理来自不同来源的令牌,并支持用于令牌验证的自定义逻辑。
首先,我们将在 或专用服务扩展方法中设置身份验证服务。我们的目标是支持多个 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 => { });
}
}
自定义身份验证处理程序将使我们能够执行更复杂的身份验证方案,例如针对数据库验证令牌。下面是如何创建自定义身份验证处理程序的示例。
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);
}
}
该方法允许您根据传入请求动态选择要使用的身份验证方案。以下是我们如何配置它。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");
}
}
要验证设置,请执行以下操作:
通过使用 .NET 8 在 ASP.NET Core 中设置多个身份验证方案,可以轻松管理各种客户端方案的不同身份验证要求。这种方法不仅提高了身份验证基础设施的灵活性,还使您的应用程序能够适应未来需求,以便根据需要集成其他身份验证方法。