以编程方式生成请求验证令牌
Programmatically generating request verification token
从一个空的 MVC 项目开始,这是我的 Startup.cs
:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace AntiForgeryExample
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseStatusCodePages();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
这是我的 HomeController.cs
:
using Microsoft.AspNetCore.Mvc;
using System.Net;
namespace AntiForgeryExample
{
public class XyzController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
[HttpGet]
public ContentResult Efg()
{
return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content = @"<!DOCTYPE html>
<html>
<body>
<form method=""post"" action=""/Xyz/Fgh"">
<button type=""submit"">123</Button>
</form>
</body>
</html>"
};
}
}
}
下面Startup.cs
行添加防伪中间件:
services.AddMvc();
因此,如果我们转到 http://localhost:52838/Xyz/Efg
,我们将获得只有一个按钮的简单页面:
如果我们按下按钮,我们会收到 400“错误请求”响应:
我假设这是因为我们没有通过有效的请求验证令牌作为 post 的一部分。 Fgh
方法应用了 ValidateAntiForgeryToken
属性:
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
因此调用该方法时需要token。
如 this page 所述,如果您将 form
标签助手与 ASP.NET Core MVC 或 Razor 页面一起使用,通常会自动包含此令牌的代码。它看起来像这样,并作为 form
标签的一部分包含在内:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
在我上面显示的示例程序中,我们以编程方式生成具有以下形式的 HTML。
我的问题是,是否有一种方法可以从 C# 中以编程方式生成所需的令牌,而无需使用 MVC 视图或 Razor 页面。我们的想法是,我们将获得令牌值,然后包含 input
标签:
<input name="__RequestVerificationToken" type="hidden" value="TOKEN VALUE HERE">
我在 /r/dotnet
subreddit 上分享了这个问题。
/u/kenos1
在那里提供了 very helpful answer:
You can inject Microsoft.AspNetCore.Antiforgery.IAntiforgery and call GetTokens() on it.
Here’s the documentation: link
正如他在那里提到的,我们在 XyzController
构造函数中注入 IAntiforgery
:
private IAntiforgery antiforgery;
public XyzController(IAntiforgery antiforgery_)
{
antiforgery = antiforgery_;
}
我们在注入的 IAntiforgery
实例上调用 GetAndStoreTokens
:
var token_set = antiforgery.GetAndStoreTokens(HttpContext);
最后,我们在生成的 HTML:
中使用生成的令牌
return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content = string.Format(@"<!DOCTYPE html>
<html>
<body>
<form method=""post"" action=""/Xyz/Fgh"">
<button type=""submit"">123</Button>
<input name=""__RequestVerificationToken"" type=""hidden"" value=""{0}"">
</form>
</body>
</html>",
token_set.RequestToken)
};
这里是完整的控制器文件:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Net;
namespace AntiForgeryExample
{
public class XyzController : Controller
{
private IAntiforgery antiforgery;
public XyzController(IAntiforgery antiforgery_)
{
antiforgery = antiforgery_;
}
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
[HttpGet]
public ContentResult Efg()
{
var token_set = antiforgery.GetAndStoreTokens(HttpContext);
return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content = string.Format(@"<!DOCTYPE html>
<html>
<body>
<form method=""post"" action=""/Xyz/Fgh"">
<button type=""submit"">123</Button>
<input name=""__RequestVerificationToken"" type=""hidden"" value=""{0}"">
</form>
</body>
</html>",
token_set.RequestToken)
};
}
}
}
官方 ASP.NET Core 3.1 文档提到 GetAndStoreTokens
方法 here。
从一个空的 MVC 项目开始,这是我的 Startup.cs
:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace AntiForgeryExample
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseStatusCodePages();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
这是我的 HomeController.cs
:
using Microsoft.AspNetCore.Mvc;
using System.Net;
namespace AntiForgeryExample
{
public class XyzController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
[HttpGet]
public ContentResult Efg()
{
return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content = @"<!DOCTYPE html>
<html>
<body>
<form method=""post"" action=""/Xyz/Fgh"">
<button type=""submit"">123</Button>
</form>
</body>
</html>"
};
}
}
}
下面Startup.cs
行添加防伪中间件:
services.AddMvc();
因此,如果我们转到 http://localhost:52838/Xyz/Efg
,我们将获得只有一个按钮的简单页面:
如果我们按下按钮,我们会收到 400“错误请求”响应:
我假设这是因为我们没有通过有效的请求验证令牌作为 post 的一部分。 Fgh
方法应用了 ValidateAntiForgeryToken
属性:
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
因此调用该方法时需要token。
如 this page 所述,如果您将 form
标签助手与 ASP.NET Core MVC 或 Razor 页面一起使用,通常会自动包含此令牌的代码。它看起来像这样,并作为 form
标签的一部分包含在内:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
在我上面显示的示例程序中,我们以编程方式生成具有以下形式的 HTML。
我的问题是,是否有一种方法可以从 C# 中以编程方式生成所需的令牌,而无需使用 MVC 视图或 Razor 页面。我们的想法是,我们将获得令牌值,然后包含 input
标签:
<input name="__RequestVerificationToken" type="hidden" value="TOKEN VALUE HERE">
我在 /r/dotnet
subreddit 上分享了这个问题。
/u/kenos1
在那里提供了 very helpful answer:
You can inject Microsoft.AspNetCore.Antiforgery.IAntiforgery and call GetTokens() on it.
Here’s the documentation: link
正如他在那里提到的,我们在 XyzController
构造函数中注入 IAntiforgery
:
private IAntiforgery antiforgery;
public XyzController(IAntiforgery antiforgery_)
{
antiforgery = antiforgery_;
}
我们在注入的 IAntiforgery
实例上调用 GetAndStoreTokens
:
var token_set = antiforgery.GetAndStoreTokens(HttpContext);
最后,我们在生成的 HTML:
中使用生成的令牌return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content = string.Format(@"<!DOCTYPE html>
<html>
<body>
<form method=""post"" action=""/Xyz/Fgh"">
<button type=""submit"">123</Button>
<input name=""__RequestVerificationToken"" type=""hidden"" value=""{0}"">
</form>
</body>
</html>",
token_set.RequestToken)
};
这里是完整的控制器文件:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Net;
namespace AntiForgeryExample
{
public class XyzController : Controller
{
private IAntiforgery antiforgery;
public XyzController(IAntiforgery antiforgery_)
{
antiforgery = antiforgery_;
}
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
[HttpGet]
public ContentResult Efg()
{
var token_set = antiforgery.GetAndStoreTokens(HttpContext);
return new ContentResult()
{
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
Content = string.Format(@"<!DOCTYPE html>
<html>
<body>
<form method=""post"" action=""/Xyz/Fgh"">
<button type=""submit"">123</Button>
<input name=""__RequestVerificationToken"" type=""hidden"" value=""{0}"">
</form>
</body>
</html>",
token_set.RequestToken)
};
}
}
}
官方 ASP.NET Core 3.1 文档提到 GetAndStoreTokens
方法 here。