如何保护托管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的授权属性直接控制访问:
- 删除原有的
UseStaticFiles(针对/SellerFiles)配置 - 新增控制器:
[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
相关产品推荐
相关产品推荐

