You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.Net Core API令牌认证:第三方系统免重复登录方案咨询

跨系统API免重复认证可行方案

针对你需要让外部系统无需定期登录刷新令牌即可调用API的需求,以下是几种落地性强的方案:

方案一:独立API密钥认证(与JWT共存)

直接新增一套基于固定密钥的认证逻辑,和现有JwtBearer认证并行,外部系统请求时携带专属API密钥即可通过验证,无需令牌刷新。

实现步骤:

  1. 定义API密钥配置
    在appsettings.json中添加密钥配置(建议加密存储或存于配置中心):
"ApiKeySettings": {
  "ValidApiKey": "YourStaticSecureApiKeyHere",
  "ApiKeyHeaderName": "X-API-Key"
}
  1. 实现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));
    }
}
  1. 注册双认证方案
    在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();
});
  1. 外部系统调用方式
    请求时在Header中携带X-API-Key: YourStaticSecureApiKeyHere即可访问API。

优缺点:

  • 优点:实现简单,不影响原有JWT逻辑,外部系统无需处理令牌刷新
  • 缺点:密钥泄露风险高,需定期轮换;默认无细粒度权限控制,可通过扩展Claims实现

方案二:超长期限JWT令牌(带吊销机制)

为外部系统生成超长期限的JWT,同时配套黑名单机制解决令牌泄露后的吊销问题。

实现步骤:

  1. 生成超长期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);
  1. 添加令牌吊销验证
    用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客户端凭证流,专为服务间认证设计,支持自动静默刷新令牌,外部系统无需人工干预。

实现步骤:

  1. 配置认证服务客户端
    在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") });
  1. API端配置认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = "https://your-identity-server-url";
        options.Audience = "ApiScope";
    });
  1. 外部系统自动获取令牌
    外部系统在后台定时调用认证接口刷新令牌:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:08:12