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

IdentityServer 6:如何在应用内部获取用户访问令牌?

在IdentityServer 6中内部获取用户访问令牌的方案

1. 配置专门的测试客户端

首先在IdentityServer的客户端配置中添加一个用于QA测试的独立客户端,避免将IdentityServer自身作为客户端:

public static IEnumerable<Client> GetClients()
{
    return new List<Client>
    {
        new Client
        {
            ClientId = "qa-test-client",
            ClientName = "QA测试专用客户端",
            AllowedGrantTypes = GrantTypes.Code,
            RequirePkce = true, // 启用PKCE提升流程安全性
            RedirectUris = { "https://your-idsrv-domain/qa/show-token" }, // 回调到内部测试页面
            PostLogoutRedirectUris = { "https://your-idsrv-domain/qa/logout" },
            AllowedScopes = { "openid", "profile", "api1", "api2" }, // 包含需要测试的API范围
            AllowOfflineAccess = false,
            RequireClientSecret = false, // 内部测试客户端无需密钥
            AccessTokenLifetime = 3600 // 设置合适的令牌有效期
        }
    };
}

2. 创建测试页面控制器

新建控制器处理令牌请求和交换逻辑,利用IdentityServer内置服务完成授权码流程:

public class QaController : Controller
{
    private readonly IIdentityServerInteractionService _interaction;
    private readonly ITokenService _tokenService;

    public QaController(IIdentityServerInteractionService interaction, ITokenService tokenService)
    {
        _interaction = interaction;
        _tokenService = tokenService;
    }

    // 触发授权流程获取授权码
    public IActionResult RequestToken()
    {
        var redirectUrl = Url.Action(nameof(ShowToken), "Qa");
        var props = new AuthenticationProperties
        {
            RedirectUri = redirectUrl,
            Items =
            {
                { "client_id", "qa-test-client" },
                { "scope", "openid profile api1 api2" }
            }
        };

        // 生成PKCE验证所需的code_verifier和code_challenge
        var codeVerifier = CryptoRandom.CreateUniqueId(32);
        var codeChallenge = codeVerifier.ToCodeChallenge();
        
        // 将code_verifier存入Cookie,后续交换令牌时使用
        Response.Cookies.Append("code_verifier", codeVerifier, new CookieOptions
        {
            HttpOnly = true,
            Secure = true,
            SameSite = SameSiteMode.Strict
        });

        props.Items.Add("code_challenge", codeChallenge);
        props.Items.Add("code_challenge_method", "S256");

        // 触发IdentityServer的授权流程
        return Challenge(props, IdentityServerConstants.DefaultCookieAuthenticationScheme);
    }

    // 回调页面:交换授权码为访问令牌并展示
    public async Task<IActionResult> ShowToken(string code)
    {
        if (string.IsNullOrEmpty(code))
        {
            return RedirectToAction(nameof(RequestToken));
        }

        var codeVerifier = Request.Cookies["code_verifier"];
        if (string.IsNullOrEmpty(codeVerifier))
        {
            return View("Error", "PKCE验证失败");
        }

        // 构造令牌交换请求
        var tokenRequest = new TokenRequest
        {
            ClientId = "qa-test-client",
            GrantType = GrantTypes.Code,
            Code = code,
            RedirectUri = Url.Action(nameof(ShowToken), "Qa"),
            CodeVerifier = codeVerifier
        };

        // 调用内置服务交换令牌
        var tokenResponse = await _tokenService.CreateTokenAsync(tokenRequest);
        if (tokenResponse.IsError)
        {
            return View("Error", tokenResponse.ErrorDescription ?? tokenResponse.Error);
        }

        // 清理临时Cookie
        Response.Cookies.Delete("code_verifier");

        return View(tokenResponse);
    }
}

3. 创建令牌展示视图

新建Razor视图(ShowToken.cshtml)用于展示令牌信息:

@{
    ViewData["Title"] = "QA测试令牌";
}

<h1>用户访问令牌信息</h1>

<div class="card">
    <div class="card-body">
        <h5 class="card-title">访问令牌</h5>
        <pre class="card-text">@Model.AccessToken</pre>
    </div>
</div>

<div class="card mt-3">
    <div class="card-body">
        <h5 class="card-title">令牌类型</h5>
        <p class="card-text">@Model.TokenType</p>
    </div>
</div>

<div class="card mt-3">
    <div class="card-body">
        <h5 class="card-title">过期时间(秒)</h5>
        <p class="card-text">@Model.ExpiresIn</p>
    </div>
</div>

<div class="card mt-3">
    <div class="card-body">
        <h5 class="card-title">ID Token(可选)</h5>
        <pre class="card-text">@Model.IdentityToken</pre>
    </div>
</div>

<a asp-action="RequestToken" class="btn btn-primary mt-3">重新获取令牌</a>

4. 关键说明

  • 该方案完全遵循OAuth2/OpenID Connect规范,通过独立测试客户端完成令牌获取,避免将IdentityServer自身作为客户端。
  • PKCE机制确保了授权流程的安全性,防止授权码被劫持。
  • 令牌生成完全由IdentityServer内置逻辑处理,符合你配置的API范围、有效期等规则。
  • QA团队只需访问/qa/requesttoken,登录后即可获取当前用户的访问令牌,用于API测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:35:23