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

.NET Core集成Azure AD认证后,如何提取并自动携带令牌?

解决方案:Azure AD认证后自动处理Swagger令牌

一、提取并保存令牌到Cookie(适配Swagger前端场景)

.NET Core中可以通过OpenID Connect的认证事件捕获令牌,存入Cookie后让Swagger自动携带,无需手动复制。

1. 配置认证事件捕获令牌

在Program.cs的认证配置中,通过OnAuthorizationCodeReceived事件获取访问令牌并写入Cookie:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

// 配置交互式OpenID Connect认证流
builder.Services.AddAuthentication()
    .AddOpenIdConnect(options =>
    {
        builder.Configuration.Bind("AzureAd", options);
        options.ResponseType = "code id_token";
        options.Scope.Add("api://{你的API资源ID}/access_as_user"); // 替换为实际API权限
        
        options.Events = new OpenIdConnectEvents
        {
            OnAuthorizationCodeReceived = async context =>
            {
                // 获取用户访问令牌
                var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
                var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(
                    new[] { "api://{你的API资源ID}/access_as_user" },
                    authenticationScheme: OpenIdConnectDefaults.AuthenticationScheme,
                    user: context.Principal);
                
                // 将令牌写入Cookie,设置安全属性
                context.HttpContext.Response.Cookies.Append("SwaggerAccessToken", accessToken, new CookieOptions
                {
                    HttpOnly = false, // 允许Swagger的JS读取
                    Secure = builder.Environment.IsProduction(), // 生产环境强制HTTPS
                    SameSite = SameSiteMode.Lax,
                    Expires = DateTimeOffset.UtcNow.AddHours(1) // 和令牌过期时间同步
                });
                
                // 清理认证流程的临时参数,重定向到干净的Swagger页面
                context.HandleCodeRedemption();
                context.Response.Redirect("/swagger");
            }
        };
    });

2. 让Swagger自动携带Cookie中的令牌

修改Swagger配置,注入自定义JS拦截请求,自动添加Authorization头:

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "你的API", Version = "v1" });
    
    // 添加Bearer认证定义
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "JWT授权头,格式为Bearer {token}"
    });
    
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
            },
            Array.Empty<string>()
        }
    });
});

// 注入自定义JS到Swagger UI
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "你的API V1");
    c.InjectJavascript("/swagger-custom.js");
});

在wwwroot目录下创建swagger-custom.js,实现Cookie读取和请求拦截:

// 从Cookie中获取令牌
function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

// 拦截Swagger的请求,自动添加Authorization头
const originalFetch = window.fetch;
window.fetch = function(resource, options) {
    const token = getCookie('SwaggerAccessToken');
    if (token) {
        options = options || {};
        options.headers = options.headers || {};
        options.headers['Authorization'] = `Bearer ${token}`;
    }
    return originalFetch(resource, options);
};

二、临时方案:直接提取令牌字符串(不推荐生产环境)

如果无法使用Cookie存储,可以在认证后将令牌作为参数传递到Swagger,再通过JS提取并填充到授权栏:

1. 修改重定向逻辑携带令牌

options.Events = new OpenApiConnectEvents
{
    OnAuthorizationCodeReceived = async context =>
    {
        var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
        var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(
            new[] { "api://{你的API资源ID}/access_as_user" },
            authenticationScheme: OpenIdConnectDefaults.AuthenticationScheme,
            user: context.Principal);
        
        // 重定向到Swagger并携带令牌(仅临时测试用)
        context.Response.Redirect($"/swagger?access_token={accessToken}");
        context.HandleCodeRedemption();
    }
};

2. 在Swagger中提取并填充令牌

修改swagger-custom.js实现URL参数提取:

// 从URL参数中获取令牌
function getUrlParam(name) {
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.get(name);
}

window.onload = function() {
    const token = getUrlParam('access_token');
    if (token) {
        // 自动填充Swagger的Bearer令牌输入框
        const authInput = document.querySelector('input[type="text"][placeholder="Enter value"]');
        if (authInput) {
            authInput.value = token;
            // 自动触发授权按钮点击
            const authButton = authInput.parentElement.querySelector('button');
            if (authButton) authButton.click();
        }
        // 清理URL中的令牌参数,避免泄露
        window.history.replaceState({}, document.title, window.location.pathname);
    }
};

关键说明

  • 你之前无法读取/swagger/access_token的URL,是因为Azure AD的认证回调地址是/signin-oidc,令牌由OpenID Connect中间件处理,必须在认证事件中捕获,而非直接读取Swagger的页面URL。
  • 生产环境优先使用Cookie方案,务必开启HTTPS和Secure=true,降低令牌泄露风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:32:45