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

如何保护托管Blazor WebAssembly应用的文件下载权限?

解决方案

1. 修正服务器端授权服务配置

托管式Blazor WebAssembly的服务器项目需要使用完整的ASP.NET Core授权服务,将AddAuthorizationCore替换为AddAuthorization:

builder.Services.AddAuthorization(options =>
{    
    var type = typeof(Permissions);

    foreach (var permission in type.GetFields())
    {
        var permissionValue = permission.GetValue(null)?.ToString();
        if (string.IsNullOrEmpty(permissionValue)) continue;
        
        options.AddPolicy(
            permissionValue,
            policyBuilder => policyBuilder.RequireAssertion(
                context => context.User.HasClaim(claim => 
                    claim.Type == "Permissions" && claim.Value == permissionValue)));
    }

    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

2. 为/SellerFiles路径添加授权检查

静态文件中间件不会自动触发授权验证,必须将/SellerFiles的请求纳入授权管道,以下是两种推荐方案:

方案一:使用Map+RequireAuthorization(直接控制静态文件访问)

移除原有的独立UseStaticFiles配置,改用Map为/SellerFiles路径创建独立管道,先做授权检查再返回静态文件:

// 放在app.UseAuthorization()之后
app.Map("/SellerFiles", appBuilder =>
{
    appBuilder.UseAuthorization();
    appBuilder.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(builder.Environment.ContentRootPath, "Uploads")),
        RequestPath = "/SellerFiles"
    });
}).RequireAuthorization(); // 应用回退策略(要求已认证用户)

如果需要限制为特定权限/角色,可指定策略名称:

.RequireAuthorization("YourDownloadPermissionPolicy");

方案二:使用控制器代理文件下载(更灵活,支持细粒度权限)

创建控制器处理文件下载请求,利用ASP.NET Core的授权属性直接控制访问:

  1. 删除原有的UseStaticFiles(针对/SellerFiles)配置
  2. 新增控制器:
[ApiController]
[Route("SellerFiles")]
[Authorize] // 或指定策略:[Authorize(Policy = "YourDownloadPermissionPolicy")]
public class SellerFilesController : ControllerBase
{
    private readonly IWebHostEnvironment _env;

    public SellerFilesController(IWebHostEnvironment env)
    {
        _env = env;
    }

    // 支持子文件夹路径:例如 /SellerFiles/docs/report.pdf
    [HttpGet("{**filePath}")]
    public IActionResult DownloadFile(string filePath)
    {
        // 防止路径遍历攻击,确保请求的文件在Uploads目录内
        var uploadsRoot = Path.GetFullPath(Path.Combine(_env.ContentRootPath, "Uploads"));
        var fullFilePath = Path.GetFullPath(Path.Combine(uploadsRoot, filePath));
        
        if (!fullFilePath.StartsWith(uploadsRoot, StringComparison.OrdinalIgnoreCase))
        {
            return Forbid();
        }

        if (!System.IO.File.Exists(fullFilePath))
        {
            return NotFound();
        }

        // 获取文件MIME类型
        var contentType = "application/octet-stream";
        var contentTypeProvider = new FileExtensionContentTypeProvider();
        contentTypeProvider.TryGetContentType(filePath, out contentType);

        return PhysicalFile(fullFilePath, contentType, Path.GetFileName(filePath));
    }
}

3. 验证管道顺序

确保服务器管道核心顺序正确:

app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseAuthentication(); // 先执行认证
app.UseAuthorization();  // 再执行授权
// 其他中间件(如BlazorFrameworkFiles、MapControllers等)
// 方案一的Map配置或方案二的控制器已自动整合到管道中

完成以上配置后,匿名用户访问/SellerFiles路径会被拒绝,只有已认证(或符合权限要求)的用户才能下载文件。

内容的提问来源于stack exchange,提问作者David.Warwick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:57:36