ASP.Net Core API令牌认证:第三方系统免重复登录方案咨询
跨系统API免重复认证可行方案
针对你需要让外部系统无需定期登录刷新令牌即可调用API的需求,以下是几种落地性强的方案:
方案一:独立API密钥认证(与JWT共存)
直接新增一套基于固定密钥的认证逻辑,和现有JwtBearer认证并行,外部系统请求时携带专属API密钥即可通过验证,无需令牌刷新。
实现步骤:
- 定义API密钥配置
在appsettings.json中添加密钥配置(建议加密存储或存于配置中心):
"ApiKeySettings": { "ValidApiKey": "YourStaticSecureApiKeyHere", "ApiKeyHeaderName": "X-API-Key" }
- 实现API密钥验证Handler
创建自定义认证处理类:
public class ApiKeyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { private readonly IConfiguration _configuration; public ApiKeyAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IConfiguration configuration) : base(options, logger, encoder, clock) { _configuration = configuration; } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { if (!Request.Headers.TryGetValue(_configuration["ApiKeySettings:ApiKeyHeaderName"], out var apiKeyHeaderValue)) { return Task.FromResult(AuthenticateResult.Fail("API密钥未提供")); } var validApiKey = _configuration["ApiKeySettings:ValidApiKey"]; if (!apiKeyHeaderValue.Equals(validApiKey, StringComparison.OrdinalIgnoreCase)) { return Task.FromResult(AuthenticateResult.Fail("无效的API密钥")); } var claims = new[] { new Claim(ClaimTypes.Name, "ExternalSystem") }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return Task.FromResult(AuthenticateResult.Success(ticket)); } }
- 注册双认证方案
在Program.cs中同时配置JWT和API密钥认证:
builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { // 保留原有JWT验证配置 options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }) .AddScheme<AuthenticationSchemeOptions, ApiKeyAuthenticationHandler>("ApiKey", options => { }); // 配置授权策略支持两种认证方式 builder.Services.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme, "ApiKey") .Build(); });
- 外部系统调用方式
请求时在Header中携带X-API-Key: YourStaticSecureApiKeyHere即可访问API。
优缺点:
- 优点:实现简单,不影响原有JWT逻辑,外部系统无需处理令牌刷新
- 缺点:密钥泄露风险高,需定期轮换;默认无细粒度权限控制,可通过扩展Claims实现
方案二:超长期限JWT令牌(带吊销机制)
为外部系统生成超长期限的JWT,同时配套黑名单机制解决令牌泄露后的吊销问题。
实现步骤:
- 生成超长期JWT
为外部系统单独生成有效期极长的令牌,并添加专属Claim标识身份:
var claims = new[] { new Claim(ClaimTypes.NameIdentifier, "ExternalSystemId"), new Claim("IsSystemClient", "true") }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: builder.Configuration["Jwt:Issuer"], audience: builder.Configuration["Jwt:Audience"], claims: claims, expires: DateTime.Now.AddYears(10), signingCredentials: creds); var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
- 添加令牌吊销验证
用Redis或数据库存储失效令牌ID,在JWT验证时检查黑名单:
options.Events = new JwtBearerEvents { OnTokenValidated = async context => { var tokenId = context.SecurityToken.Id; var redis = context.HttpContext.RequestServices.GetRequiredService<IDatabase>(); var isRevoked = await redis.StringGetAsync($"RevokedToken:{tokenId}"); if (!string.IsNullOrEmpty(isRevoked)) { context.Fail("令牌已被吊销"); } } };
优缺点:
- 优点:复用原有JWT逻辑,支持权限细分
- 缺点:令牌长期有效存在泄露风险,需维护吊销机制;密钥轮换时需重新生成令牌
方案三:OAuth2客户端凭证模式
采用标准OAuth2客户端凭证流,专为服务间认证设计,支持自动静默刷新令牌,外部系统无需人工干预。
实现步骤:
- 配置认证服务客户端
在IdentityServer等认证服务中注册外部系统客户端:
builder.Services.AddIdentityServer() .AddInMemoryClients(new List<Client> { new Client { ClientId = "ExternalSystemClient", ClientSecrets = { new Secret("ClientSecretHere".Sha256()) }, AllowedGrantTypes = GrantTypes.ClientCredentials, AllowedScopes = { "ApiScope" }, AccessTokenLifetime = 86400 * 30 // 设置30天有效期 } }) .AddInMemoryApiScopes(new List<ApiScope> { new ApiScope("ApiScope") });
- API端配置认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = "https://your-identity-server-url"; options.Audience = "ApiScope"; });
- 外部系统自动获取令牌
外部系统在后台定时调用认证接口刷新令牌:
var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync("https://your-identity-server-url"); if (disco.IsError) throw new Exception(disco.Error); var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { Address = disco.TokenEndpoint, ClientId = "ExternalSystemClient", ClientSecret = "ClientSecretHere", Scope = "ApiScope" }); if (tokenResponse.IsError) throw new Exception(tokenResponse.Error); // 使用tokenResponse.AccessToken发起API请求
优缺点:
- 优点:符合标准协议,安全规范,支持细粒度权限控制,令牌可自动刷新
- 缺点:需搭建或集成认证服务,实现复杂度较高
内容的提问来源于stack exchange,提问作者TaCqz
相关产品推荐
相关产品推荐

