为了调用应用了 AntiforgeryToken 的 API,我编写了一个像这样的 HttpClient。
[HttpPost]
public async Task<IActionResult> PhoneNumberAuth(int app_idx, string memberPhone)
{
....
....
HttpClient client = new HttpClient();
string url = "https://" + HttpContext.Request.Host.ToString() + Url.Action("PhoneNumberAuth", "Api")!;
AntiforgeryTokenSet requestTokenSet = _antiforgery.GetAndStoreTokens(HttpContext);
string requestTokenHeaderName = requestTokenSet.HeaderName!;
string requestToken = requestTokenSet.RequestToken!;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add(requestTokenHeaderName, requestToken);
var authenticationNumber = new
{
receiveNumber = memberPhone,
senderNumber = smsInfo.sms_phoneNumber
};
string dataJson = Newtonsoft.Json.JsonConvert.SerializeObject(authenticationNumber);
StringContent content = new StringContent(dataJson, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
return Ok();
}
但是,这将导致 400 Bad Request 错误。
如果我将 [IgnoreAntiforgeryToken] 属性应用于 API,我将得到 200 OK 而不是错误。
[IgnoreAntiforgeryToken]
[HttpPost("[Action]")]
public async Task<IActionResult> PhoneNumberAuth()
{
...
return Ok();
}
请注意,两个 PhoneNumberAuth 方法存在于不同的控制器中。
为什么会出现错误?
在视图中,我通过 Javascript 调用 PhoneNumberAuth(int app_idx, string memberPhone) 方法,该方法又调用 PhoneNumberAuth API。
我不直接调用PhoneNumberAuth API,因为我们需要处理敏感信息。
我无法应用 [IgnoreAntiforgeryToken] 属性,也无法创建这样的操作方法。
代币会出错吗?
View 是这样处理的
@{
var requestToken = Antiforgery.GetAndStoreTokens(Context);
}
...
$.ajax({
url: '@Url.Action("PhoneNumberAuth", "Api")',
headers:
{
'@requestToken.HeaderName': '@requestToken.RequestToken'
},
type: 'post',
success: function(result) {
},
error: function(ajaxContext) {
}
});
为了在控制器的操作方法中调用它(PhoneNumberAuth(int app_idx,string memberPhone)),我在cs中编写了以下内容。
private readonly IAntiforgery _antiforgery;
public SiteController(IAntiforgery antiforgery)
{
_antiforgery = antiforgery;
}
...
AntiforgeryTokenSet requestTokenSet = _antiforgery.GetAndStoreTokens(HttpContext);
我在这段代码中遗漏了什么吗?
请注意,无需应用防伪造令牌保护来防止 ASP.NET CORE Web API 中的 CSRF 攻击。
如果您想保护您的API,您可以尝试将此类基于Token等的身份验证和授权机制集成到您的API项目中。
如果您确实想使用API端点实现AntiforgeryToken验证,您可以参考以下示例代码。
// Add Antiforgery services
builder.Services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
builder.Services.AddControllersWithViews(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
//...
控制器和动作
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IAntiforgery _antiforgery;
public ValuesController(IAntiforgery antiforgery)
{
_antiforgery = antiforgery;
}
[HttpGet("GetToken")]
public IActionResult GetToken()
{
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
return Ok(new { token = tokens.RequestToken });
}
[ValidateAntiForgeryToken]
[HttpPost("[Action]")]
public async Task<IActionResult> PhoneNumberAuth()
{
//...
return Ok("success");
}
//...
示例和测试请求
###
# get token
GET https://localhost:7014/api/values/GetToken HTTP/1.1
###
# make request with XSRF token
POST https://localhost:7014/api/values/PhoneNumberAuth HTTP/1.1
X-XSRF-TOKEN: CfDJ8KmhRjRu7cpNjZEYjJecX1dG8RozjhyUrthrU0kNYV-9auYN47VfKORxLOo_9G78ElX14Wcx2kQmXn9tJiRSIj6REVu0c2Z1iENmm7BaBwmxxGyB_hB2L2olrRKSY3ZeZS8Bl44eU6OS0zkho4FZKAE
测试结果