我在服务器端使用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 错误请求,并且它成功验证了伪造令牌。
我不知道如何解决这个问题。
如果您使用
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”。
希望对您有帮助!
我遇到了类似的问题,但通过在我的请求中添加“RequestVerificationToken”解决了问题
我的控制器代码(示例)
HttpPost(“退出”) 使用 JWT 授权 ==> 验证防伪令牌 */
一种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());
}
文档建议使用 AutoValidateAntiforgeryToken 代替。切换到 AutoValidateAntiforgeryToken 确实解决了我的问题。我也推荐它。