以编程方式生成请求验证令牌 [英] Programmatically generating request verification token

查看:57
本文介绍了以编程方式生成请求验证令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从一个空的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆