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

如何在IdentityServer4的API方法中获取客户端信息以设置默认值

在IdentityServer4 API中根据调用客户端设置默认值

我有一个基于IdentityServer4的项目,API里的创建方法需要根据调用接口的客户端(比如客户端名称)设置默认值。具体场景是:用户注册API会被多个带不同ClientId和ClientName(比如"MobileAPP"、"Website"、"CRMAPP")的客户端调用,我想根据调用的客户端给注册数据加对应的默认值。之前试着读请求上下文没找到相关信息,只找到一种客户端日志记录的方法,但没法在API方法里直接拿到客户端信息。

相关代码

客户端定义

new Client
{
    ClientName = "Test Mobile App",
    ClientId = "test_mobile_app",
    AllowedGrantTypes = GrantTypes.ClientCredentials,
    ClientSecrets =
    {
        new Secret("mykey".Sha256())
    },
    AllowedScopes =
    {
        "app.openid",
        "app.profile",
        "user.manage"
    },
    AllowOfflineAccess = true,
    RefreshTokenUsage = TokenUsage.ReUse,
    AccessTokenLifetime = 3600,
    RefreshTokenExpiration = TokenExpiration.Absolute,
    AbsoluteRefreshTokenLifetime = 2592000
}

策略配置

option.AddPolicy("MobileAppScope", policy =>
{
    policy.RequireAuthenticatedUser();
    policy.RequireClaim("scope", "user.manage")
          .RequireClaim("scope", "app.openid")
          .RequireClaim("scope", "app.profile");
});

授权属性

[Authorize(Policy = "MobileAppScope", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

解决方案

1. 让IdentityServer把客户端信息塞进AccessToken里

修改Client定义,添加两个关键配置,让客户端的Id和Name自动包含在AccessToken的Claims中:

new Client
{
    ClientName = "Test Mobile App",
    ClientId = "test_mobile_app",
    AllowedGrantTypes = GrantTypes.ClientCredentials,
    ClientSecrets = { new Secret("mykey".Sha256()) },
    AllowedScopes = { "app.openid", "app.profile", "user.manage" },
    AllowOfflineAccess = true,
    RefreshTokenUsage = TokenUsage.ReUse,
    AccessTokenLifetime = 3600,
    RefreshTokenExpiration = TokenExpiration.Absolute,
    AbsoluteRefreshTokenLifetime = 2592000,
    // 开启客户端声明发送
    AlwaysSendClientClaims = true,
    AlwaysIncludeUserClaimsInIdToken = true,
    // 可选:手动指定要包含的客户端声明(如果自动生成的不够用)
    Claims = new List<ClientClaim>
    {
        new ClientClaim("client_id", "test_mobile_app"),
        new ClientClaim("client_name", "Test Mobile App")
    }
}

2. 配置API的JwtBearer中间件,确保声明被正确解析

在API的Program.cs(或Startup.cs)里,配置JwtBearer时,确保客户端声明不会被过滤,还能在验证后把信息存到HttpContext里:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = "https://你的IdentityServer地址";
        options.Audience = "user.manage";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = "name",
            RoleClaimType = "role",
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true
        };
        // 验证Token后把客户端信息存到HttpContext,方便后续取用
        options.Events = new JwtBearerEvents
        {
            OnTokenValidated = context =>
            {
                var clientId = context.Principal?.FindFirst("client_id")?.Value;
                var clientName = context.Principal?.FindFirst("client_name")?.Value;
                if (!string.IsNullOrEmpty(clientId))
                {
                    context.HttpContext.Items["ClientId"] = clientId;
                }
                if (!string.IsNullOrEmpty(clientName))
                {
                    context.HttpContext.Items["ClientName"] = clientName;
                }
                return Task.CompletedTask;
            }
        };
    });

3. 在API方法里直接获取客户端信息并设置默认值

现在在Controller的注册方法里,就能直接从User.Claims或者HttpContext.Items里拿到客户端信息,然后设置对应默认值:

[Authorize(Policy = "MobileAppScope", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpPost("register")]
public IActionResult RegisterUser([FromBody] UserRegisterDto dto)
{
    // 从Claims里拿客户端信息
    var clientId = User.FindFirst("client_id")?.Value;
    var clientName = User.FindFirst("client_name")?.Value;

    // 根据客户端设置默认值
    if (clientName == "Test Mobile App")
    {
        dto.DefaultRole = "MobileUser";
        dto.Source = "MobileApp";
    }
    else if (clientName == "Website")
    {
        dto.DefaultRole = "WebUser";
        dto.Source = "Website";
    }

    // 执行注册逻辑...
    return Ok("用户注册成功");
}

4. 可选:针对不同客户端做权限控制

如果需要限制某些客户端才能调用接口,可以修改策略,加上客户端声明的校验:

option.AddPolicy("MobileAppOnly", policy =>
{
    policy.RequireAuthenticatedUser();
    policy.RequireClaim("client_id", "test_mobile_app");
    policy.RequireClaim("scope", "user.manage", "app.openid", "app.profile");
});

内容的提问来源于stack exchange,提问作者Syed Ahsan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 21:20:25