为什么我的 ASP.net 核心应用程序不接受手动生成的令牌

Why my ASP.net core application does not accept manually generated tokens

为什么我的 ASP.net 核心应用程序不接受手动生成的令牌

对于 Ajax 请求,我通过请求发送 header 令牌和 cookie 令牌

这是我用来创建 header 令牌的代码

public class TokenController : Controller
{
    private readonly IAntiforgery _antiforgery;

    public TokenController(IAntiforgery antiforgery)
    {
        _antiforgery = antiforgery;
    }

    [HttpGet]
    public ActionResult GetHeaderToken()
    {
        var tokens = _antiforgery.GetTokens(HttpContext);

        return Json(tokens.RequestToken);
    }
}

Startup.cs:

public class Startup
{
    //...
    public void ConfigureServices(IServiceCollection services)
    {
        //...
        services.AddAntiforgery(options =>
        {
            options.HeaderName = "HeaderToken";
            options.FormFieldName = "FieldToken";
            options.Cookie = new CookieBuilder
            {
                Name = "CookieToken",
                IsEssential = true,
                HttpOnly = true,
                SecurePolicy = CookieSecurePolicy.SameAsRequest,
                SameSite = SameSiteMode.Lax
            };
        });

        services.AddControllers(options =>
        {
            options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
        });

        services.AddRazorPages(options =>
        {
            options.Conventions
                .ConfigureFilter(new AutoValidateAntiforgeryTokenAttribute());
        })
        .AddRazorRuntimeCompilation();
    }
}

js:

$.ajax = function(options)
{
    return new Promise(async (resolve, reject) =>
    {
        var xhr = new XMLHttpRequest();

        xhr.open(options.method, options.url, true);

        xhr.onerror = function()
        {
            //...
        };

        xhr.onload = function()
        {
            //...
        };

        if (options.method.toLowerCase() === 'get')
        {
            xhr.send($.param(options.data));
        }
        else
        {
            var data = options.data;

            var $tokenField = $(`[name="FieldToken"]`);

            if ($tokenField.length === 0)
            {
                await $.ajax({
                    url: 'Token/GetHeaderToken',
                    method: 'get',
                    complete: function(x)
                    {
                         data["FieldToken"] = x.responseText;
                    }
                });
            }
            else
            {
                data["FieldToken"] = $tokenField.first().val();
            }

            xhr.send(getFormData(options.data));
        }
    });
};

您可以从表单元素中获取令牌:

TokenController.cs

public class TokenController : Controller
{
    [HttpGet]
    [Route("[controller]")]
    public ActionResult Index()
    {
        return PartialView("Token");
    }
}

Token.cshtml:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<form method="post"></form>

js:

$.ajax = function(options)
{
    return new Promise(async (resolve, reject) =>
    {
        var xhr = new XMLHttpRequest();

        xhr.onerror = function()
        {
            //...
        };

        xhr.onload = function()
        {
            //...
        };

        if (options.method.toLowerCase() === 'get')
        {
            xhr.open(options.method, `${options.url}?${$.param(options.data)}`, true);

            xhr.send();
        }
        else
        {
            var $tokenField = $(`[name="FieldToken"]`);

            if ($tokenField.length === 0)
            {
                await $.ajax({
                    url: 'Token/GetHeaderToken',
                    method: 'get',
                    complete: function(x)
                    {
                        $('body').append(x.responseText);
                    }
                });

                $tokenField = $(`[name="FieldToken"]`);
            }

            xhr.open(options.method, options.url, true);

            xhr.setRequestHeader("HeaderToken", $tokenField.first().val());

            xhr.send(getFormData(options.data));
        }
    });
};