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

如何在单点登录项目中向Identity Server 4传递应用名称

在IdentityServer4中传递Application Name的几种实用方案

嘿,我来帮你搞定这个问题!在IdentityServer4(IS4)里传递你的application-name其实有几种贴合不同场景的方式,我给你拆解清楚:

1. 单应用对应独立Client:用ClientName配置

如果你的每个业务应用都在IS4中注册了单独的Client,那最简单的方式就是直接在Client配置里设置ClientName字段——IS4会自动把这个名称和对应的授权请求关联起来。

IS4端配置示例

在你的IS4配置类(比如Config.cs)里,给目标Client添加ClientName:

public static IEnumerable<Client> GetClients()
{
    return new List<Client>
    {
        new Client
        {
            ClientId = "your-app-client-id",
            ClientName = "你的Application Name", // 这里就是要传递的应用名称
            AllowedGrantTypes = GrantTypes.Code,
            RedirectUris = { "https://your-app.com/signin-oidc" },
            PostLogoutRedirectUris = { "https://your-app.com/signout-callback-oidc" },
            AllowedScopes = { "openid", "profile", "api1" },
            // 其他必要配置...
        }
    };
}

在IS4中获取这个名称

在登录页面、授权逻辑里,你可以通过客户端存储获取当前请求对应的Client信息:

// 注入IClientStore
private readonly IClientStore _clientStore;
private readonly IIdentityServerInteractionService _interaction;

public async Task<IActionResult> Login(string returnUrl)
{
    var authContext = await _interaction.GetAuthorizationContextAsync(returnUrl);
    if (authContext != null)
    {
        var client = await _clientStore.FindClientByIdAsync(authContext.ClientId);
        var appName = client.ClientName; // 拿到你的应用名称
        // 可以把appName传递给视图,比如显示在登录页面标题上
        ViewBag.AppName = appName;
    }
    // 其他登录逻辑...
}

2. 多应用共用一个Client:通过自定义请求参数传递

如果多个业务应用共用同一个IS4 ClientId,那你可以在发起授权请求时,手动添加application-name作为自定义参数。

应用端发起请求时添加参数

不管你用的是OIDC客户端库(比如ASP.NET Core的OpenID Connect中间件)还是手动构造URL,都可以加上这个参数:

  • 手动构造URL示例:
    https://your-is4-server/connect/authorize?
    client_id=shared-client-id
    &redirect_uri=https://your-app.com/callback
    &response_type=code
    &scope=openid profile
    &application-name=你的应用名称 // 自定义参数
    
  • ASP.NET Core中间件配置示例:
    services.AddAuthentication(options =>
    {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
    })
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
        options.Authority = "https://your-is4-server";
        options.ClientId = "shared-client-id";
        options.ResponseType = "code";
        // 自定义授权请求参数
        options.Events = new OpenIdConnectEvents
        {
            OnRedirectToIdentityProvider = context =>
            {
                context.ProtocolMessage.SetParameter("application-name", "你的应用名称");
                return Task.CompletedTask;
            }
        };
        // 其他配置...
    });
    

在IS4中获取自定义参数

在IS4的授权逻辑里,你可以从授权上下文的请求参数中提取这个值:

public async Task<IActionResult> Login(string returnUrl)
{
    var authContext = await _interaction.GetAuthorizationContextAsync(returnUrl);
    if (authContext != null)
    {
        // 从请求Query中获取自定义参数
        var appName = authContext.Request.Query["application-name"].FirstOrDefault();
        // 如果需要在整个流程中保留这个值,可以存入上下文Properties
        authContext.Properties.Items["application-name"] = appName;
    }
    // 其他逻辑...
}

3. 把Application Name加入Token:通过ProfileService添加自定义Claim

如果希望用户登录后,application-name作为Claim出现在ID Token或Access Token中,供业务应用直接使用,那可以通过自定义IProfileService实现。

实现自定义ProfileService

public class CustomProfileService : IProfileService
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IIdentityServerInteractionService _interaction;
    private readonly IClientStore _clientStore;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public CustomProfileService(UserManager<ApplicationUser> userManager, 
                                IIdentityServerInteractionService interaction,
                                IClientStore clientStore,
                                IHttpContextAccessor httpContextAccessor)
    {
        _userManager = userManager;
        _interaction = interaction;
        _clientStore = clientStore;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(sub);
        if (user == null)
        {
            throw new ArgumentException("用户不存在");
        }

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, user.UserName),
            new Claim(ClaimTypes.Email, user.Email)
        };

        // 获取application-name并添加为Claim
        var returnUrl = _httpContextAccessor.HttpContext.Request.Query["returnUrl"].FirstOrDefault();
        var authContext = await _interaction.GetAuthorizationContextAsync(returnUrl);
        var appName = authContext?.Request.Query["application-name"].FirstOrDefault() 
                      ?? (await _clientStore.FindClientByIdAsync(authContext.ClientId)).ClientName;
        
        claims.Add(new Claim("application-name", appName));

        context.IssuedClaims = claims;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(sub);
        context.IsActive = user != null;
    }
}

注册ProfileService到IS4

在Startup.cs的ConfigureServices里添加:

services.AddIdentityServer()
    .AddProfileService<CustomProfileService>()
    // 其他IS4配置(AddInMemoryClients、AddInMemoryIdentityResources等)...

这样,业务应用在获取Token后,就能从Claims中直接取出application-name了。


内容的提问来源于stack exchange,提问作者A.J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:18:03