如何在带授权的Blazor Server应用中安全上传图片并保护API路由
如何保护API上传路由仅允许登录用户访问
我在Razor页面中使用RadzenUpload控件上传文件,代码如下:
<RadzenUpload Accept="image/*" Progress=@OnProgress class="w-100" Url=@($"/api/upload/uploadfirmlogo")/>
上传请求会发送到/api/upload/uploadfirmlogo,对应的控制器代码如下:
[ApiController] [Microsoft.AspNetCore.Mvc.Route("api/[controller]")] //[Authorize] public class UploadController : Controller { private readonly IWebHostEnvironment environment; public UploadController(IWebHostEnvironment environment) { this.environment = environment; } [HttpPost("UploadFirmLogo")] public async Task<IActionResult> UploadFirmLogoAsync(IFormFile[] files) { try { if (HttpContext.Request.Form.Files.Any()) { var file = HttpContext.Request.Form.Files[0]; string path = Path.Combine(environment.WebRootPath, "images", "logos", file.FileName); using (var stream = new FileStream(path, FileMode.Create)) { await file.CopyToAsync(stream); } } return StatusCode(200); } catch (Exception ex) { return StatusCode(500, ex.Message); } } }
我的应用使用AuthenticationStateProvider处理登录流程,但不知道如何保护这个上传路由,只允许当前登录用户访问。
解决方案
1. 启用控制器/接口的认证授权
直接取消控制器上[Authorize]的注释,即可让整个UploadController的所有接口强制要求用户登录后才能访问:
[ApiController] [Microsoft.AspNetCore.Mvc.Route("api/[controller]")] [Authorize] // 启用授权验证 public class UploadController : Controller { // 控制器原有代码不变 }
如果只想单独保护UploadFirmLogo接口,也可以把[Authorize]标注在该方法上:
[HttpPost("UploadFirmLogo")] [Authorize] // 仅对该上传接口启用授权 public async Task<IActionResult> UploadFirmLogoAsync(IFormFile[] files) { // 方法原有代码不变 }
2. 确保RadzenUpload携带认证凭证
RadzenUpload通过AJAX发送请求,需保证请求能带上当前用户的认证信息:
- 若使用Cookie认证:ASP.NET Core默认会自动在AJAX请求中携带认证Cookie,无需额外配置。
- 若使用JWT令牌:需要在Razor页面中获取令牌,并通过RadzenUpload的
Headers属性添加认证头:
修改RadzenUpload控件添加请求头:@inject AuthenticationStateProvider AuthStateProvider @code { private string _authToken; protected override async Task OnInitializedAsync() { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); _authToken = authState.User.FindFirst("access_token")?.Value; } }<RadzenUpload Accept="image/*" Progress=@OnProgress class="w-100" Url=@($"/api/upload/uploadfirmlogo") Headers=@(new Dictionary<string, string> { {"Authorization", $"Bearer {_authToken}" } }) />
3. 额外安全加固措施
- 验证文件合法性:不要仅依赖前端的
Accept属性(可被篡改),在控制器内验证文件类型和大小:var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif" }; var extension = Path.GetExtension(file.FileName).ToLower(); if (!allowedExtensions.Contains(extension)) { return BadRequest("仅允许上传图片格式文件"); } // 限制文件大小(示例:最大10MB) if (file.Length > 10 * 1024 * 1024) { return BadRequest("文件大小不能超过10MB"); } - 避免文件名冲突与安全风险:不要直接使用用户上传的文件名,生成唯一文件名存储:
var uniqueFileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; string path = Path.Combine(environment.WebRootPath, "images", "logos", uniqueFileName); - 细粒度权限控制(可选):如果需要限制特定角色用户上传,可使用
[Authorize(Roles = "Admin")],或在方法内获取用户信息判断:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); // 根据userId校验用户是否拥有上传权限
内容的提问来源于stack exchange,提问作者D A
相关产品推荐
相关产品推荐

