如何为现有令牌服务配置ASP.NET Core客户端Web应用身份验证?
配置独立STS的ASP.NET Admin客户端认证与API调用
一、启动时配置认证服务器(关联独立STS)
不管你用的是Startup.cs还是.NET 6+的Program.cs,核心是把Cookie认证和OpenID Connect(OIDC)结合,指向你的独立STS服务,同时配置保存令牌以便后续调用API。
关键配置代码(以.NET 6+为例):
var builder = WebApplication.CreateBuilder(args); // 添加认证服务 builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { // 你的独立STS服务地址 options.Authority = "https://your-sts-api-url"; // 客户端ID(需在STS提前注册) options.ClientId = "admin-client"; // 客户端密钥(STS对应配置) options.ClientSecret = "your-client-secret"; // 响应类型,需与STS支持的一致,例如code+token+id_token options.ResponseType = "code id_token token"; // 请求的权限(资源服务器的API范围) options.Scope.Add("api-resource-scope"); options.Scope.Add("openid"); options.Scope.Add("profile"); // 核心配置:将获取到的令牌保存到Cookie,供后续API调用使用 options.SaveTokens = true; // 回调地址,需与STS注册的一致 options.CallbackPath = "/signin-oidc"; // 登出回调地址 options.SignedOutCallbackPath = "/signout-callback-oidc"; // 令牌验证参数配置 options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = "role" }; }); // 注册HttpContextAccessor,用于后续获取当前用户令牌 builder.Services.AddHttpContextAccessor(); var app = builder.Build(); // 启用认证、授权中间件(顺序不能错) app.UseAuthentication(); app.UseAuthorization(); // 其他中间件配置... app.Run();
配置要点:
Authority必须指向独立STS的根地址,OIDC会自动读取它的配置端点(如/.well-known/openid-configuration)SaveTokens = true是核心,只有开启这个,登录后获取的Access Token才会存储在Cookie中ResponseType要和STS的配置匹配,若用授权码流,推荐code id_token token或纯code(纯code需额外调用令牌接口换Token)- 客户端ID、密钥、回调地址必须和STS里的注册信息完全一致
二、调用资源服务器API时自动携带令牌
登录后,每次调用受保护API,需要将当前用户的Access Token放入请求头的Authorization字段。可以通过封装HttpClient自动处理,避免手动重复编码。
方法1:注册带令牌拦截器的HttpClient(推荐)
// 注册带令牌拦截的命名HttpClient builder.Services.AddHttpClient("ProtectedApiClient", client => { client.BaseAddress = new Uri("https://your-resource-api-url"); }).AddHttpMessageHandler<BearerTokenHandler>(); // 自定义令牌拦截器 public class BearerTokenHandler : DelegatingHandler { private readonly IHttpContextAccessor _httpContextAccessor; public BearerTokenHandler(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var httpContext = _httpContextAccessor.HttpContext; if (httpContext != null) { // 从当前用户认证信息中获取Access Token var accessToken = await httpContext.GetTokenAsync("access_token"); if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } } return await base.SendAsync(request, cancellationToken); } } // 注册拦截器服务 builder.Services.AddTransient<BearerTokenHandler>();
方法2:Controller内手动获取令牌(简单场景)
public class HomeController : Controller { private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContextAccessor; public HomeController(IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor) { _httpClientFactory = httpClientFactory; _httpContextAccessor = httpContextAccessor; } public async Task<IActionResult> CallProtectedApi() { var client = _httpClientFactory.CreateClient(); var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await client.GetAsync("https://your-resource-api-url/api/protected-endpoint"); // 处理API响应逻辑... return View(); } }
注意事项:
- 必须确保
IHttpContextAccessor已注册(前面配置中已添加builder.Services.AddHttpContextAccessor()) - 若STS颁发的是JWT令牌,资源服务器需能验证令牌的签名和有效期,确保双方密钥/证书一致
- 如需自动刷新过期令牌,需STS支持刷新令牌,且客户端请求时添加
offline_accessscope
内容的提问来源于stack exchange,提问作者Donald N. Mafa
相关产品推荐
相关产品推荐

