以编程方式生成请求验证令牌 [英] Programmatically generating request verification token
问题描述
从一个空的MVC项目开始,这是我的 Startup.cs
:
Starting with an empty MVC project, here's my 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
中的以下行添加了防伪中间件:
The following line in Startup.cs
adds the anti-forgery middleware:
services.AddMvc();
因此,如果转到 http://localhost:52838/Xyz/Efg
,我们将获得一个带有单个按钮的简单页面:
So, if we go to http://localhost:52838/Xyz/Efg
, we get the simple page with a single button:
如果我们按下按钮,则会收到一个400"Bad Request"(错误请求)消息,回应:
If we press the button, we get a 400 "Bad Request" response:
我认为这是因为我们没有在帖子中传递有效的请求验证令牌. Fgh
方法应用了 ValidateAntiForgeryToken
属性:
I'm assuming this is because we haven't passed a valid request verification token as part of the post. The Fgh
method has the ValidateAntiForgeryToken
attribute applied:
[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";
因此,调用此方法时需要令牌.
Thus a token is required when calling this method.
此页面,如果将 form
标记帮助程序与ASP.NET Core MVC或Razor页面一起使用,通常会自动包含此令牌的代码.它看起来像这样,并被包含在 form
标记的一部分中:
As described on this page, normally the code for this token will automatically be included if you use the form
tag helper with ASP.NET Core MVC or a Razor Page. It will look something like this and be included as part of the form
tag:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
在上面显示的示例程序中,我们正在以编程方式生成带有表单的HTML.
In the example program I show above, we're programmatically generating the HTML with the form.
我的问题是,有没有一种方法可以以编程方式从C#生成所需的令牌,而不必使用MVC视图或Razor页面.想法是,我们将获得令牌值,然后包含 input
标记:
My question is, is there a way to programmatically generate the required token from C#, without having to go through using an MVC view or Razor Page. The idea would be that we'd get the token value and then include the input
tag:
<input name="__RequestVerificationToken" type="hidden" value="TOKEN VALUE HERE">
推荐答案
我在/r/dotnet
subreddit上分享了这个问题.
I shared this question on the /r/dotnet
subreddit.
/u/kenos1
提供了非常有用的答案在那里:
您可以注入Microsoft.AspNetCore.Antiforgery.IAntiforgery并对其调用GetTokens().
You can inject Microsoft.AspNetCore.Antiforgery.IAntiforgery and call GetTokens() on it.
以下是文档:链接
正如他在那儿提到的,我们在 XyzController
构造函数中注入 IAntiforgery
:
As he mentions there, we inject IAntiforgery
at the XyzController
constructor:
private IAntiforgery antiforgery;
public XyzController(IAntiforgery antiforgery_)
{
antiforgery = antiforgery_;
}
我们在注入的 IAntiforgery
实例上调用 GetAndStoreTokens
:
We call GetAndStoreTokens
on the IAntiforgery
instance that we injected:
var token_set = antiforgery.GetAndStoreTokens(HttpContext);
最后,我们在生成的HTML中使用结果标记:
And finally, we use the resulting token in the generated 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)
};
这是完整的控制器文件:
Here is the controller file in its entirety:
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
方法
The official ASP.NET Core 3.1 documentation mentions the GetAndStoreTokens
method here.
这篇关于以编程方式生成请求验证令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!