.NET 8中CSRF Token生成及Excel上传防伪造问题求助
.NET 8 文件上传中CSRF Token的正确配置与使用
一、修复服务器端反伪造中间件缺失问题
错误的核心是未配置反伪造中间件,.NET 8默认对表单类POST请求(含multipart/form-data)强制启用反伪造验证,必须在Program.cs中按严格顺序添加中间件:
var builder = WebApplication.CreateBuilder(args); // 添加认证授权服务(按需) builder.Services.AddAuthentication(); builder.Services.AddAuthorization(); // 显式配置反伪造服务(自定义Cookie和请求头名称,可选) builder.Services.AddAntiforgery(options => { options.Cookie.Name = "XSRF-TOKEN"; options.HeaderName = "X-XSRF-TOKEN"; }); var app = builder.Build(); // 中间件顺序必须严格遵循:认证→授权→路由→反伪造→端点映射 app.UseAuthentication(); app.UseAuthorization(); app.UseRouting(); // 关键:添加反伪造中间件,位置不能错 app.UseAntiforgery(); app.UseEndpoints(endpoints => { // 保留你的上传端点逻辑 endpoints.MapPost("/uploadexlsx", async (IFormFile file) => { List<string> validextensions = new List<string>() {".xlsx"}; string extension = Path.GetExtension(file.FileName); if (!validextensions.Contains(extension)) { return $"Extention is not valid({string.Join(",", validextensions)})"; } string filename = "File1" + extension; string path = @"D:/"; try { using FileStream stream = new FileStream(Path.Combine(path, filename), FileMode.Create); await file.CopyToAsync(stream); return filename; } catch (Exception ex) { return $"Error uploading file: {ex.Message}"; } }); // 新增:提供CSRF Token的端点,供客户端获取 endpoints.MapGet("/get-csrf-token", async (HttpContext context, IAntiforgery antiforgery) => { // 生成Token并存储到Cookie var tokens = await antiforgery.GetAndStoreTokensAsync(context); // 返回请求头需要的Token值 return Results.Ok(new { XsrfToken = tokens.RequestToken }); }); }); app.Run();
二、客户端获取并携带CSRF Token
修改客户端代码,先请求/get-csrf-token获取Token,再在上传请求中加入指定请求头:
public async Task SendExcelFileToServer(string filepath, string filename, string InnerAddress) { try { using (var httpClient = new HttpClient()) { // 1. 获取CSRF Token var tokenUri = ServerAddressTextBox.Text.Trim() + "/get-csrf-token"; var tokenResponse = await httpClient.GetAsync(tokenUri); tokenResponse.EnsureSuccessStatusCode(); // 用强类型类接收更安全,替代dynamic var tokenData = await tokenResponse.Content.ReadFromJsonAsync<CsrfTokenResponse>(); // 2. 构建上传请求 string requestUri = ServerAddressTextBox.Text.Trim() + InnerAddress; using (var form = new MultipartFormDataContent()) { using (var fileContent = new ByteArrayContent(File.ReadAllBytes(filepath))) { fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); form.Add(fileContent, "file", filename); } // 添加CSRF Token到请求头 httpClient.DefaultRequestHeaders.Add("X-XSRF-TOKEN", tokenData.XsrfToken); // 发送上传请求 HttpResponseMessage response = await httpClient.PostAsync(requestUri, form); response.EnsureSuccessStatusCode(); } } } catch { MessageBox.Show("Try sending data again and check your connection!"); } } // 强类型接收Token的类 public class CsrfTokenResponse { public string XsrfToken { get; set; } }
三、Postman测试注意事项
- 先发送GET请求到
/get-csrf-token,获取返回的XsrfToken值,同时Cookie中会自动存储对应的Token。 - 在POST上传请求的Headers中添加
X-XSRF-TOKEN,值为获取到的Token。 - 确保Postman启用了Cookie自动保存(默认开启,可在Cookie面板查看)。
关键说明
- .NET 8中
GetAndValidateRequestTokenAsync已被废弃,正确生成Token的方法是IAntiforgery.GetAndStoreTokensAsync,验证用ValidateRequestAsync。 - 如果你的API仅供可信桌面/客户端调用,且能确保请求安全,可临时禁用特定端点的反伪造验证(不推荐公开API使用):
endpoints.MapPost("/uploadexlsx", async (IFormFile file) => { // 上传逻辑 }).DisableAntiforgery();
内容的提问来源于stack exchange,提问作者Kian Farooghi
相关产品推荐
相关产品推荐

