在 ASP.NET Core 中处理多个身份验证方案:使用 .NET 8 释放灵活安全性的强大功能

科技   2024-11-19 08:00   广东  

故事是关于什么的?

如果您认为在 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");
}
}

测试身份验证流程

要验证设置,请执行以下操作:

  1. 使用 Swagger:可以使用 Swagger 配置应用程序以支持基于令牌的身份验证测试。

  2. Postman 或 HTTP 客户端:使用不同的令牌发送请求,以查看策略方案如何路由到正确的身份验证处理程序。

通过使用 .NET 8 在 ASP.NET Core 中设置多个身份验证方案,可以轻松管理各种客户端方案的不同身份验证要求。这种方法不仅提高了身份验证基础设施的灵活性,还使您的应用程序能够适应未来需求,以便根据需要集成其他身份验证方法。


推荐阅读:
C#中使用 record 的好处 因为好用所以推荐!
推荐一个基于 C# 和 WPF 实现的短视频自动发布管理系统
使用 C#、OpenAI 和 Spectre.Console 创建控制台 ChatGPT 客户端
.NET 9正式发布,亮点是.NET Aspire和AI
今晚零点!一同相约 .NET Conf 2024
适用于 .NET 稳定的官方OpenAI库

点击下方卡片关注DotNet NB

一起交流学习

▲ 点击上方卡片关注DotNet NB,一起交流学习

请在公众号后台

回复 【路线图】获取.NET 2024开发者路线
回复 【原创内容】获取公众号原创内容
回复 【峰会视频】获取.NET Conf大会视频
回复 【个人简介】获取作者个人简介
回复 【年终总结】获取作者年终回顾
回复 加群加入DotNet NB 交流学习群

长按识别下方二维码,或点击阅读原文。和我一起,交流学习,分享心得。

DotNet NB
.NET 技术学习分享,社区热点分享,专注为 .NET 社区做贡献,愿我们互相交流学习,共同推动社区发展
 最新文章