【ASP.NET Core】解决“The required antiforgery cookie "xxx" is not present”
当你在页面上用 form post 内容时,可能会遇到以下异常:
The required antiforgery cookie "????????" is not present.
咱们来重现一下错误。新建一个 ASP.NET Core 项目,模板选【空】就行了,这是老周最喜欢的项目模板,空 == *。
在项目下建一个目录,叫 Pages,用来放 Razor 页面;然后建一个 Index.cshtml 页。
之所以叫 Index.cshtml,是因为 Index 是默认页的名字,这样输入根 URL 就能访问。如果不叫 Index 呢,比如这样。
此时你可以在根 URL 后面加上 demo 来访问,如果想在根目录下访问,也可以在 Startup.ConfigureServices 方法中配置页面路由。
public void ConfigureServices(IServiceCollection services) { services.AddMvc().AddRazorPagesOptions(o => { o.Conventions.AddPageRoute("/Demo", ""); }); }
写路径时一定要注意大小写,在浏览器中输入时不需要注意,但在编程时要注意。AddPageRoute 方法是个扩展方法,pagename 参数表明你要的目标页面,比如我要到达 /Demo 页,route 参数设置路由,空字符串表示根路径。即我在浏览器中输入 http://somehost/,就能定位到 http://somehost/Demo 页。
如果 pagename 为 /users/newone,route 参数为 new,那么,你访问 http://somehost/new 就会指向 http://somehost/users/newone。
你得注意的是,这个 razor page 的路由规则只用于 Web Pages,不是 MVC 的路由规则,这个设置对 MVC 是不起作用的,MVC 可以用类似 {controller]/{action}/{id} 的路由,这个相信你很熟练了(当然,前提是你写过 MVC 应用)。
顺便在 Configure 方法中加上 use 代码,不管是 Web Pages 还是 MVC 都要加上。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); }
现在可以弄一下页面了。打开页面,你发现找不到对应的 PageModel 类,这里老周推荐用 _ViewImports 文件来处理。
在 Pages 目录下添加一个视图导入文件。
然后,引入要用的命名空间。
@using WebSample09 @using WebSample09.Pages
但是这不够完善,还要加一行。
@namespace WebSample09.Pages
@namespace 指令用来设定 Razor 页所生成代码的命名空间,这样就可以确保页面与 PageModel 类型处于同一个命名空间,可以避免将来发生各种错误。
保存并关闭导入页,回到刚刚添加的页面。
@page @model DemoModel <!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" /> <title>示例</title> </head> <body> <form method="post"> <label for="parm">请随便输入:</label> <input type="text" name="parm" /> <button type="submit">提交</button> </form> </body> </html>
打开对应的 PageModel 类代码,写一个 OnPost 方法。
public void OnPost(string parm) { ViewData["data"] = $"你输入的的值是:{parm}"; }
在 POST 之后,通过 parm 参数(与页面 form 元素中字段命名相同,会自动赋值)获取输入的内容,存到 ViewData 中,为了在页面上显示,我们回到刚才的页面,加一个 p 元素,用来显示输入内容。
<p>@ViewData["data"]?.ToString()</p>
好,现在可以测试了。
运行,进入页面。
输入内容,点按钮提交,会收到 400 错误。
此时 Console Log 记录下一个异常。
即我们开头所说的那个错误,这个验证主要为了安全考虑,防止别人盗了你的数据然后跨域欺骗服务器。
那么,咋解决呢?说出来你可能不信,很简单。
打开刚刚咱们加到项目中的那个视图导入页,然后添加一个 form 元素的 Tag Helper 就行了。
@addTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
格式是这样的,很常规,就是 .net 类型的表示方法,用英文的逗号隔开,前面是类型(包括命名空间),后面是程序集名称。
添加标记帮助器前,代码编辑器中是显示为这种颜色的。
添加标记帮助器后,显示为这种颜色。
这时候就可以了。
咱们不妨对比一下,看看应用标记 Helper 前后输出到客户端的 HTML 有啥不同。
在未使用标记帮助器前,提交时会出现 400 错误,生成的 HTML 如下:
<form method="post"> <label for="parm">请随便输入:</label> <input name="parm" type="text"> <button type="submit">提交</button> </form>
基本是原文输出。
应用 form 元素帮助器后,生成的 HTML 如下:
<form method="post"> <label for="parm">请随便输入:</label> <input name="parm" type="text"> <button type="submit">提交</button> <input name="__RequestVerificationToken" type="hidden" value="CfDJ8DEAGDEorWJFuzYOfcGEJpSWrKHd5Qrw4jdARVRF3SwAS-TChnUQHEsFWxtXTk7IDCmpRAB241ucR6kdZA-sRBHnsyOe01ymGLs-DONlZYmB-MzvmXgJmKcn2ZrYMN-Br8fj25nX_zvuwzhyNQ42Das" />
</form>
多了一个名为 __RequestVerificationToken 的隐藏元素,标识当前请求会话,防止被人冒用。
顺便补充一下,如果你想导入各种 Tag Helper ,可以把类型名改为 * (星号,通配符)。
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
好了,今天的内容扯到这儿了,88。