以编程方式生成请求验证令牌

问题描述 投票:0回答:2

从一个空的 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
,我们将获得带有单个按钮的简单页面:

enter image description here

如果我们按下按钮,我们会收到 400“错误请求”响应:

enter image description here

我假设这是因为我们没有在帖子中传递有效的请求验证令牌。

Fgh
方法应用了
ValidateAntiForgeryToken
属性:

[HttpPost]
[ValidateAntiForgeryToken]
public string Fgh() => "fgh 1";

因此调用此方法时需要令牌。

本页所述,如果您将

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">
asp.net-core asp.net-core-mvc asp.net-core-3.1
2个回答
5
投票

我在

/r/dotnet
subreddit 上分享了这个问题。

/u/kenos1
在那里提供了非常有帮助的答案

您可以注入 Microsoft.AspNetCore.Antiforgery.IAntiforgery 并对其调用 GetTokens() 。

这是文档:链接

正如他在那里提到的,我们在

IAntiforgery
构造函数中注入
XyzController

private IAntiforgery antiforgery;

public XyzController(IAntiforgery antiforgery_)
{
    antiforgery = antiforgery_;
}

我们在注入的

GetAndStoreTokens
实例上调用
IAntiforgery

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
方法这里


0
投票

在最新版本的 ASP.NET Core 中,可以手动生成令牌,如下所示:

<form method="post">
  @Html.AntiForgeryToken()
</form>
© www.soinside.com 2019 - 2024. All rights reserved.