我在使用ajax的AntiForgeryToken遇到了麻烦.我正在使用ASP.NET MVC 3.我在jQuery Ajax调用和Html.AntiForgeryToken()中尝试了解决方案.使用该解决方案,现在正在传递令牌:
var data = { ... } // with token, key is '__RequestVerificationToken'
$.ajax({
type: "POST",
data: data,
datatype: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
url: myURL,
success: function (response) {
...
},
error: function (response) {
...
}
});
Run Code Online (Sandbox Code Playgroud)
当我删除[ValidateAntiForgeryToken]属性只是为了查看数据(带有令牌)是否作为参数传递给控制器时,我可以看到它们正在被传递.但由于某种原因,A required anti-forgery token was not supplied or was invalid.当我放回属性时,消息仍会弹出.
有任何想法吗?
编辑
antiforgerytoken是在表单中生成的,但我没有使用提交操作来提交它.相反,我只是使用jquery获取令牌的值,然后尝试ajax发布.
这是包含令牌的表单,位于顶部母版页:
<form id="__AjaxAntiForgeryForm" action="#" method="post">
@Html.AntiForgeryToken()
</form>
Run Code Online (Sandbox Code Playgroud) 如果它是Javascript或jQuery中的相对路径或绝对路径,我如何测试URL?我想根据传入的URL是本地路径还是外部路径来处理.
if (urlString starts with http:// or https://)
//do this
Run Code Online (Sandbox Code Playgroud) 我的SPA的某些区域需要向所有用户开放,有些区域需要身份验证.在这些领域,它是我想要保护的通过AJAX加载的数据.
我有一个身份验证服务(见下文),我在durandal main.js中添加了一个依赖项.该服务被称为:
authentication
Run Code Online (Sandbox Code Playgroud)
在我的main.js中,我打电话
authentication.handleUnauthorizedAjaxRequest(function () {
app.showMessage('You are not authorized, please login')
.then(function () {
router.navigateTo('#/user/login');
});
});
Run Code Online (Sandbox Code Playgroud)
它警告用户他们未被授权,并将用户导航到登录视图/ viewmodel,在那里他们可以输入详细信息并尝试登录.
构建此身份验证viewModel时会想到一些问题:
大多数人似乎都在创建单独的cshtml页面; 一个用于登录(如果用户未经过身份验证),通常的index.cshtml有没有充分的理由让我切换到该方法?
我在服务器端"用户控制器"上的登录操作具有我需要发送的[ValidateAntiForgeryToken]属性.
我还有一个'antiforgery'服务(见下文),我也在main.js viewModel文件中添加了一个依赖项(也在我的main.js中).
antiforgery.addAntiForgeryTokenToAjaxRequests();
Run Code Online (Sandbox Code Playgroud)
这会拦截所有ajax请求(以及内容),并将MVC AntiForgeryToken值添加到数据中.似乎完全按照我的意愿工作.如果有任何错误/错误,请告诉我.
完整认证服务如下.
// services/authentication.js
define(function (require) {
var system = require('durandal/system'),
app = require('durandal/app'),
router = require('durandal/plugins/router');
return {
handleUnauthorizedAjaxRequests: function (callback) {
if (!callback) {
return;
}
$(document).ajaxError(function (event, request, options) {
if (request.status === 401) …Run Code Online (Sandbox Code Playgroud) 有没有办法覆盖jQuery的核心功能?假设我想在大小中添加一个警告(this.length):function()而不是在源中添加它
size: function() {
alert(this.length)
return this.length;
},
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以这样做:
if (console)
{
console.log("Size of div = " + $("div").size());
var oSize = jQuery.fn.size;
jQuery.fn.size = function()
{
alert(this.length);
// Now go back to jQuery's original size()
return oSize(this);
}
console.log("Size of div = " + $("div").size());
}
Run Code Online (Sandbox Code Playgroud) 我有以下ajax.actionlink调用Delete action method删除对象: -
@if (!item.IsAlreadyAssigned(item.LabTestID))
{
string i = "Are You sure You want to delete (" + @item.Description.ToString() + ") ?";
@Ajax.ActionLink("Delete",
"Delete", "LabTest",
new { id = item.LabTestID },
new AjaxOptions
{ Confirm = i,
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
})
}
Run Code Online (Sandbox Code Playgroud)
但有一个办法,包括@Html.AntiForgeryToken()与Ajax.actionlink删除通话,以确保没有任何攻击者可以通过发送虚假的删除请求?
BR
ASP.NET MVC的AntiForgeryToken机制基于当前HttpContext.User.它在您调用时使用该值来构造令牌Html.AntiForgeryToken().基本上没关系(请参阅此处最后一段中的解释)但是当您通过Ajax调用登录时会出现问题.
在我的代码中,当用户登录时,凭据在Ajax中作为Json对象发送(AntiForgeryToken隐藏字段值也在Json内发送),服务器验证用户,应用FormsAuthentication.SetAuthCookie(),并返回Json结果包含一些用户特定的数据.这样,我可以在登录时避免整页刷新.
问题是现在每个后续的Ajax请求都会失败ValidateAntiForgeryTokenAttribute,因为它现在需要一个与防伪cookie不兼容的防伪标记.
如何将有效的防伪标记放入客户端的隐藏字段中,以便登录后的每个Json请求都会成功?
我试图手动获取一个新的隐藏字段标记(AntiForgery.GetHtml()在操作上使用,提取标记字符串本身,将其返回到Json中的客户端并在JavaScript中手动将其放置在防伪隐藏字段中)但它不起作用 - ValidateAntiForgeryTokenAttribute服务器上的后续Ajax调用失败.事实上,每次调用AntiForgery.GetHtml()(基本上是Html.AntiForgeryToken()帮助程序所做的)都会产生一个不同的令牌,这会使前一个令牌失效.
我也试着设置HttpContext.User = new GenericPrincipal(new GenericIdentity(email), null);详见这里,但它不工作.
注意: 由于我的具体情况,此解决方案对我不起作用:Ajax 登录更改服务器上的用户身份,因此登录前生成的每个令牌都无效; 此解决方案也不适用,因为它解决了不同的问题.
我为这个问题的接受答案中描述的解决方案实现了Razor等价物: jQuery Ajax调用和Html.AntiForgeryToken() 但是我一直得到以下异常:
System.Web.Mvc.HttpAntiForgeryException(0x80004005):不存在所需的防伪表单字段"__RequestVerificationToken".
编辑
我这样做是为了解决这个问题:
function AddAntiForgeryToken(data) {
data.append('__RequestVerificationToken',$('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val());
return data;
};
function CallAjax(url, type, data, success, error) {
var ajaxOptions = { url: url, type: type, contentType: 'application/json'};
if (type == 'POST') {
var fd = new window.FormData();
fd = AddAntiForgeryToken(fd);
$.each(data, function (i, n) {
fd.append(i,n);
});
data = fd;
ajaxOptions.processData = false;
ajaxOptions.contentType = false;
}
ajaxOptions.data = data;
if (success) ajaxOptions.success = success;
//If there is a custom error handler nullify the general …Run Code Online (Sandbox Code Playgroud) 我基本上需要在我的Web API控制器中防止跨站点请求伪造,这是MVC应用程序的一部分.我对任何想法持开放态度.此时,我有一个MVC视图,它使用ArcGIS for JavaScript API显示Esri地图.用户在地图上创建路线,并且可以通过AJAX POST保存其穿过的路线和各种功能.视图没有表单.这是因为我POST到服务器的所有数据都在内存中,而且在屏幕上(或在隐藏字段中)不可见.
所以,我在MVC视图中有以下内容来获取防伪令牌:
@functions{
public string GetTokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
Run Code Online (Sandbox Code Playgroud)
我在View中有这个隐藏的输入,但是意识到这很糟糕,因为它既有'form token',也有与AntiForgery.Validation一起使用的cookie令牌:
<input type="hidden" id="antiforgeryToken" value="@GetTokenHeaderValue()" />
Run Code Online (Sandbox Code Playgroud)
然后,在一个单独的JavaScript文件中(不在View中的脚本标记中),我正在对我的Web API Controller进行Http POST.这是我将令牌添加到请求标头的位置:
var headers = {};
headers['RequestVerificationToken'] = $("#antiforgeryToken").val();
// Ajax POST to Web API Controller
$.ajax({
async: true,
url: '/api/RouteData',
type: 'POST',
headers: headers,
data: requestData,
dataType: 'json',
error: function (xhr, statusText, errorThrown) {
console.log('Error saving route data! ' + errorThrown);
}, …Run Code Online (Sandbox Code Playgroud) 为解决CSRF问题,我使用Ajax的客户端设置:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the …Run Code Online (Sandbox Code Playgroud) 我正在阅读AntiForgeryToken,但不了解实际使用或重要性.我看到人们写了一个像他们一样的代码
@using (Html.BeginForm("Create", "Register"))
{
@Html.AntiForgeryToken()
}
Run Code Online (Sandbox Code Playgroud)
所以它做了什么......它将生成一个唯一的令牌,当表单发布时,这个唯一的toke将通过,并且cookie将传递相同的唯一令牌值,并且两个唯一数据将在服务器端比较两者都是是否平等.如果没有,则发生一些篡改.
我只是不明白其他形式字段值是否会改变或篡改然后如何确定篡改.假设我们经常在隐藏字段中存储有价值的数据.如果我需要确保隐藏的字段价值,那么AntiForgeryToken如何帮助我们?
我们可以使用AntiForgeryToken将这些有价值的数据包装在其中,然后在服务器端进行比较.
任何人都可以给我一些示例代码,通过它我可以在我的页面中放入3个有价值的数据,如果篡改,那么将向用户显示友好的消息.指导我如何做到这一点.谢谢
当我无法保证客户端将使用哪个平台时,我[Authorize]在严格(即View较少)的ASP.NET Core WebAPI项目中使用注释时遇到了问题.也就是说,应用程序需要是一个真正的API,不需要特定的平台来访问.
注意:当我说"严格的WebAPI"时,我的项目实际上是作为由...生成的MVC项目开始的.
Run Code Online (Sandbox Code Playgroud)dotnet new mvc --auth Individual...我立即从中删除了所有视图等,并更改了路由首选项以匹配WebAPI约定.
当我通过AJAX访问标准登录功能(在下面的粘贴中剥离到基本要素)时,我获得了一个JSON有效负载并返回了一个cookie.
[HttpPost("apiTest")]
[AllowAnonymous]
public async Task<IActionResult> ApiLoginTest([FromBody] LoginViewModel model, string returnUrl = null)
{
object ret = new { Error = "Generic Error" };
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
ret = new { Success = true };
else
ret = new { Error = "Invalid login attempt" };
}
return new ObjectResult(ret);
}
Run Code Online (Sandbox Code Playgroud)
成功时,返回类似于以下内容的cookie:
.AspNetCore.Identity.Application=CfDJ8Ge9E-[many characters …Run Code Online (Sandbox Code Playgroud)