ASP.NET Core 6.0中IAntiforgery使用问题及解决过程
解决ASP.NET Core 6.0拆分Program与Startup后的防伪造令牌配置问题
问题还原
之前在ASP.NET Core 5.0的Startup.Configure方法中,能通过构造注入IAntiforgery正常实现为受保护路由生成自定义请求头的功能(适配React前端)。但升级到6.0后,因将所有代码集中在Program.cs会引发依赖注入、授权异常,于是拆分到独立的Program和Startup文件,却发现无法沿用5.0的Configure方法签名直接注入IAntiforgery。
5.0可运行代码示例
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery) { app.UseEndpoints(endpoints => { endpoints.MapGet("antiforgery/token", context => { var tokens = antiforgery.GetAndStoreTokens(context); context.Response.Headers.Append("XYZ", tokens.RequestToken!); return Task.FromResult(StatusCodes.Status200OK); }); endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); }); }
6.0拆分后的尝试代码(Program.cs)
var startup = new dolpassword.Startup(builder.Configuration); startup.ConfigureServices(builder.Services); var app = builder.Build(); startup.Configure(app,app.Environment);
遇到的语法错误
参考官方示例时,在Configure方法中调用app.Services.GetRequiredService<IAntiforgery>()出现语法错误:
app.UseRouting(); app.UseAuthorization(); // 6.0的Configure中app.Services语法报错 var antiforgery = **app.Services.GetRequiredService<IAntiforgery>();** app.Use((context, next) => { var requestPath = context.Request.Path.Value; if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase) || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase)) { var tokenSet = antiforgery.GetAndStoreTokens(context); context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!, new CookieOptions { HttpOnly = false }); } return next(context); });
解决方案
方案一:直接通过方法参数注入(推荐)
在6.0拆分的Startup类中,完全可以沿用5.0的写法,直接在Configure方法的参数列表里注入IAntiforgery,依赖注入会自动解析该服务,无需通过app.Services获取。修改后的Configure方法如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery) { app.UseRouting(); app.UseAuthorization(); app.Use((context, next) => { var requestPath = context.Request.Path.Value; if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase) || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase)) { var tokenSet = antiforgery.GetAndStoreTokens(context); context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!, new CookieOptions { HttpOnly = false }); } return next(context); }); app.UseEndpoints(endpoints => { endpoints.MapGet("antiforgery/token", context => { var tokens = antiforgery.GetAndStoreTokens(context); context.Response.Headers.Append("XYZ", tokens.RequestToken!); return Task.FromResult(StatusCodes.Status200OK); }); endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); }); }
保持Program.cs的调用逻辑不变即可,这种方式符合ASP.NET Core依赖注入的最佳实践。
方案二:修复app.Services调用的语法问题
如果坚持使用app.Services获取服务,只需去掉代码中多余的**符号即可(这是导致语法错误的原因):
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
内容的提问来源于stack exchange,提问作者Charles Owen
相关产品推荐
相关产品推荐

