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

如何在Blazor客户端的JS文件下载函数中传入Bearer授权Token?

Blazor客户端授权API文件下载:Bearer Token传递方案

核心问题原因

直接通过浏览器URL跳转下载时,浏览器不会自动携带Bearer Token到请求头里,这就是加了[Authorize]后返回401的根本原因。下面是三种可行的解决方案,按推荐优先级排序:


方案一:通过HttpClient获取流后触发下载(推荐)

利用Blazor内置的HttpClient(已集成Token管理)先从API拉取文件流,再通过JS将流转为Blob触发下载,既安全又避免了URL跳转的Token传递问题。

前端代码(Blazor组件)

@inject HttpClient Http
@inject IJSRuntime JSRuntime

<button @onclick="DownloadAuthorizedFile">下载授权文件</button>

@code {
    private async Task DownloadAuthorizedFile()
    {
        // 调用授权API,HttpClient会自动携带Bearer Token
        var response = await Http.GetAsync("api/files/export", HttpCompletionOption.ResponseHeadersRead);
        response.EnsureSuccessStatusCode();

        // 从响应头提取文件名(API需在Content-Disposition中返回)
        var fileName = response.Content.Headers.ContentDisposition?.FileNameStar 
                       ?? response.Content.Headers.ContentDisposition?.FileName 
                       ?? "exported-file";
        fileName = fileName.Trim('"'); // 去掉可能存在的引号

        // 获取文件流并调用JS触发下载
        using var streamRef = new DotNetStreamReference(await response.Content.ReadAsStreamAsync());
        await JSRuntime.InvokeVoidAsync("downloadFromStream", fileName, streamRef);
    }
}

配套JS代码(放在wwwroot/js/utils.js或index.html中)

window.downloadFromStream = async (fileName, streamRef) => {
    const stream = await streamRef.stream();
    const blob = new Blob([stream]);
    const downloadUrl = URL.createObjectURL(blob);
    
    const anchor = document.createElement('a');
    anchor.href = downloadUrl;
    anchor.download = fileName;
    anchor.click();
    
    URL.revokeObjectURL(downloadUrl);
    anchor.remove();
};

方案二:Token作为查询参数传递(仅适合非敏感场景)

如果必须用URL跳转方式(比如超大文件不想占用客户端内存),可以将Token编码后放在查询参数里,但注意查询参数可能被日志记录,仅适合非敏感文件且必须在HTTPS环境下使用。

前端代码

@inject IJSRuntime JSRuntime
@inject IAccessTokenProvider TokenProvider

private async Task TriggerDownloadWithQueryToken()
{
    var tokenResult = await TokenProvider.RequestAccessToken();
    if (tokenResult.TryGetToken(out var token))
    {
        // 对Token进行URL编码,避免特殊字符问题
        var encodedToken = Uri.EscapeDataString(token.Value);
        var downloadUrl = $"api/files/export?authToken={encodedToken}";
        await JSRuntime.InvokeVoidAsync("triggerFileDownload", downloadUrl);
    }
}

API端修改(读取查询参数验证Token)

[Authorize]
[HttpGet("export")]
public IActionResult ExportFile([FromQuery] string authToken)
{
    // 手动验证Token逻辑(可复用原有JWT验证逻辑)
    var validationResult = _jwtValidator.ValidateToken(authToken);
    if (!validationResult.IsValid)
    {
        return Unauthorized();
    }

    // 返回文件逻辑
    var fileBytes = System.IO.File.ReadAllBytes("path/to/target/file");
    return File(fileBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "data.xlsx");
}

方案三:Cookie传递Token(需同域配置)

如果你的Blazor客户端和API处于同域(或子域),可以将Token写入Cookie,让浏览器自动携带。之前失败大概率是Cookie配置问题,以下是正确配置方式:

Blazor客户端登录后设置Cookie

@inject IJSRuntime JSRuntime

private async Task PersistTokenToCookie(string token)
{
    // 设置Secure、SameSite=Strict确保安全,maxAge按实际过期时间设置
    await JSRuntime.InvokeVoidAsync("setAuthCookie", "BearerToken", token, "/", 3600);
}

配套JS代码

window.setAuthCookie = (name, value, path, maxAge) => {
    document.cookie = `${name}=${value}; path=${path}; max-age=${maxAge}; secure; same-site=strict`;
};

API端配置(从Cookie读取Token)

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            // 原有JWT验证参数(Issuer、Audience、SigningKey等)
        };

        // 添加从Cookie读取Token的逻辑
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var token = context.Request.Cookies["BearerToken"];
                if (!string.IsNullOrEmpty(token))
                {
                    context.Token = token;
                }
                return Task.CompletedTask;
            }
        };
    });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 09:43:22