当我使用“ValidateAntiForgeryToken”和“Authorize”时收到 400 错误请求

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

我在服务器端使用asp.net core,在客户端使用xamarin。我使用JWT令牌,我想同时验证伪造令牌。

这是我的客户端代码:

 public async Task<string> PostAsync(object model, string url)
        {
            var cookieContainer = new CookieContainer();
            var handlerhttps = new HttpClientHandler
            {
                UseCookies = true,
                UseDefaultCredentials = true,
                CookieContainer = cookieContainer
            };

            var clientPage = new HttpClient(handler: handlerhttps)
            {
                BaseAddress = new Uri(uriString: Application.Current.Resources[index: "Domain"] + "/api/token")
            };

            var pageWithToken = await clientPage.GetAsync(requestUri: clientPage.BaseAddress);
            var verificationToken = await pageWithToken.Content.ReadAsStringAsync();
            using (var handler = new HttpClientHandler
            {
                CookieContainer = cookieContainer,
                UseDefaultCredentials = true,
                UseCookies = true
            })
            {
                using (var client = new HttpClient(handler: handler) {BaseAddress = new Uri(uriString: url)})
                {
                    client.DefaultRequestHeaders.Add(name: "RequestVerificationToken", value: verificationToken);
                    if (Application.Current.Properties[key: "Token"] != null)
                    {
                        var token = Application.Current.Properties[key: "Token"].ToString();
                        client.DefaultRequestHeaders.Authorization =
                            new AuthenticationHeaderValue(scheme: "Bearer", parameter: token);
                    }


                    var json = JsonConvert.SerializeObject(value: model);
                    var content = new StringContent(content: json, encoding: Encoding.UTF8,
                        mediaType: "application/json");
                    var response = await client.PostAsync(requestUri: client.BaseAddress, content: content);
                    var result = await response.Content.ReadAsStringAsync();
                    return result;
                }
            }
        } 

我的问题是当我在服务器端同时使用

[ValidateAntiForgeryToken]
[Authorize]
时,我收到 400 错误请求。

但是当我删除

[ValidateAntiForgeryToken]
时,它会毫无问题地授权。

当我删除

[Authorize]
时,我没有收到 400 错误请求,并且它成功验证了伪造令牌。

我不知道如何解决这个问题。

xamarin asp.net-core-mvc jwt dotnet-httpclient antiforgerytoken
4个回答
2
投票

如果您使用

Microsoft.AspNetCore.Mvc.TagHelpers
,它将添加一个带有“难以猜测”代码的输入字段:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8PXv-VNSuRBLvOlUgHlQcf4p8B29vW6EKn4ENesSgHR79kWTvbnQ9a1Taj90b-e66-79H7Nx5ljHnvPbwqfSNqHMRMaBkoRKGsTxtbZZlq0rSl2zbGK2aKpPQc0qnoNuRehSNhP097P5-Vlp-3OSPYdIqLQJSqIsPDaQsEOXsNU4qIIDrj-tIhqk5EW9tTYc6g">

反正就算加了

@Html.AntiForgeryToken()
也不冲突。但是,您不能用
[ValidateAntiForgeryToken]
装饰“第一个”控制器操作,只有最后一个 才会获得 POST。

示例:

行动1

[HttpPost]
[AllowAnonymous]
[ActionName("SpecialSignUp")]
public IActionResult Index([FromForm] string email)
{
    // TODO : code in here
    return View(email);
}

用户将通过 POST 重定向到上述操作。

假设上面的视图显示了一个表单,其中已预先填写了电子邮件字段并需要填写其他字段。

如果您用

[ValidateAntiForgeryToken]
装饰它,您将得到 400(错误请求)。去掉它,一切都会好的。

行动2

[HttpPost]
[AllowAnonymous] // It could be [Authorized]
[ActionName("SpecialSignUp")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LaunchSignUpAsync([FromForm] SpecialSignUpViewModel model)
{
    // TODO : Code in here
    return RedirectToAction("OtherActionX", data);
}

表格将由上述View发布

现在一切正常,不再发生冲突。如果您尊重该顺序,它将对您有用!

我也遇到了同样的问题,它之所以发生是因为我也用

[ValidateAntiForgeryToken]
装饰了“Action 1”。

希望对您有帮助!


0
投票

我遇到了类似的问题,但通过在我的请求中添加“RequestVerificationToken”解决了问题

我的控制器代码(示例)

HttpPost(“退出”) 使用 JWT 授权 ==> 验证防伪令牌 */


0
投票

一种CSRF防范机制,服务器通过比较请求头中的token值与cookie中的token值来验证CSRF token。

创建一个新文件并添加它。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Project.Decorators
{
public class CSRFAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // The idea is to compare token from cookie and http header
        bool res = false;
        string? csrfTokenHeader = context.HttpContext.Request.Headers["X-XSRF-TOKEN"];
        var cookies =  context.HttpContext.Request.Cookies;
        string csrfFromCookie = string.Empty;
        foreach (var i in cookies){
            if (i.Key == "XSRF-TOKEN")
            {
                csrfFromCookie = i.Value.Trim();
            }
        }
        Console.WriteLine(csrfFromCookie + " COOKIE \n");
        Console.WriteLine(csrfTokenHeader + " HEADER");
        if (csrfFromCookie == csrfTokenHeader)
        {
            Console.WriteLine(true);
            res = true;
        }
        if (!res)
        {
            context.Result = new StatusCodeResult(403);
        }
        else
        {
            base.OnActionExecuting(context);
        }
    }
}
}

例如提出请求时

  fetch("/your_url", {
  method: "get",
  credentials: "include",
  headers: {
    "Content-Type": "application/json",
    "X-XSRF-TOKEN": getCookieValue("XSRF-TOKEN"),
    'Authorization': 'Bearer ' + "token"
  },
}).then(res => console.log(res));

function getCookieValue(name) {
// Search for the cookie name followed by an equals sign
var regex = new RegExp("(?:(?:^|.*;)\\s*" + name + "\\s*\\=\\s* 
([^;]*).*$)|^.*$");
var cookieValue = document.cookie.replace(regex, "$1");
return cookieValue;
}

然后在您的端点中

    [HttpPost]
    [Route("your_url")]
    [CSRF]
    [Authorize]
    public IActionResult Test() {
        return new JsonResult(Ok());
    }

0
投票

文档建议使用 AutoValidateAntiforgeryToken 代替。切换到 AutoValidateAntiforgeryToken 确实解决了我的问题。我也推荐它。

https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-8.0#automatically-validate-antiforgery-tokens-for-unsafe-http-methods-仅限

© www.soinside.com 2019 - 2024. All rights reserved.