|
|
Danh hiệu: Administration
Nhóm: Administrators
Gia nhập: 23-07-2013(UTC) Bài viết: 6,117   Đến từ: Vietnam Cảm ơn: 10 lần Được cảm ơn: 2 lần trong 2 bài viết
|
The jQuery PieceNow we need jQuery to grab this CSRF token and use it in our requests. Due to the fancy new jQuery prefilters, this is actually a tiny little chunk of code:
Mã:$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
var verificationToken = $("meta[name='__RequestVerificationToken']").attr('content');
if (verificationToken) {
jqXHR.setRequestHeader("X-Request-Verification-Token", verificationToken);
}
});
or Mã:// Setup CSRF safety for AJAX:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (options.type.toUpperCase() === "POST") {
// We need to add the verificationToken to all POSTs
var token = $("input[name^=__RequestVerificationToken]").first();
if (!token.length) return; var tokenName = token.attr("name"); // If the data is JSON, then we need to put the token in the QueryString:
if (options.contentType.indexOf('application/json') === 0) {
// Add the token to the URL, because we can't add it to the JSON data:
options.url += ((options.url.indexOf("?") === -1) ? "?" : "&") + token.serialize();
} else if (typeof options.data === 'string' && options.data.indexOf(tokenName) === -1) {
// Append to the data string:
options.data += (options.data ? "&" : "") + token.serialize();
}
}
});
Source : https://gist.github.com/scottrippey/3428114 or Mã:$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$(document).ajaxSend(function (event, request, opt) {
if (opt.hasContent && securityToken) { // handle all verbs with content
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (opt.contentType !== false || event.contentType) {
request.setRequestHeader( "Content-Type", opt.contentType);
}
}
});
});
Very clean, and we don’t have to mess with any of our requests (you could technically do this if you used ajaxSetup’s “beforeSend” option). Note: jQuery Ajax script doesn't add a Content-Type
In other words, all things you have to do is ensure that the "__RequestVerificationToken" input is included in the POST request. The other half of the information (i.e. the token in the user's cookie) is already sent automatically with an AJAX POST request, e.g Mã:$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {
"__RequestVerificationToken":
$("input[name=__RequestVerificationToken]").val()
},
success: function (response) {
// ....
}
});
});
The Backend PieceNow that we have this verification token getting passed in the header, we just need to verify this token somewhere. The first thing that I did was to copy the ValidateAntiForgeryTokenAttribute class. Inside of the ValidateAntiForgeryTokenAttribute there is a line that looks like this: Mã:string formValue = context.Request.Form[fieldName];
All we need to do is to grab the value from the header instead of the field:
Mã:string formValue =
context.Request.Headers[EpicAntiForgeryData.GetAntiForgeryTokenHeaderName()];
Now we can let the class do the rest of the work. And Finally…Now all you have to do is put your new AjaxValidateAntiForgeryToken attribute on your controller actions that you want to validate. When your Ajax event fires, jQuery will append the token to the call then when it hits your controller action, the attribute plucks the value out of the header and the cookie, then it does its magic. You just have to keep in mind that you can’t use the same classes for posting forms regularly anymore, since the header won’t get appended to a non-ajax post. Download Sample Files
Solution for global valdiation by using Http Header instead of modifying form collection:It is nice and concise and forces you to check all of your HttpPosts, not just some of them. It uses HTTP headers instead of trying to modify the form collection. ClientMã:var token = $('[name=__RequestVerificationToken]').val();
$.ajax({
type: 'POST',
url: '/Home/Ajax',
cache: false,
headers: { '__RequestVerificationToken': token },
contentType: 'application/json; charset=utf-8',
data: { title: 'This is my title', contents: 'These are my contents' },
success: function () {
...
},
error: function () {
...
}
});
The important part of the JS above is the headers: { "__RequestVerificationToken": token }. This means that you can decorate your base controller with this new ValidateAntiForgeryTokenOnAllPosts attribute, and then all forms in your application will no longer work until you put @Html.AntiForgeryToken() in your form. ServerA generic attribute is written to decorate a controller class. It is used to validate POST actions and work with ajax posts where you put the anti forgery token in the headers for the request. The attribute class looks like this: Mã:[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
public override void OnAuthorization( AuthorizationContext filterContext )
{
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null
? antiForgeryCookie.Value
: null;
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
}
}
Source : codethinked.com
|
|
|
|
|
|
Di chuyển
Bạn không thể tạo chủ đề mới trong diễn đàn này.
Bạn không thể trả lời chủ đề trong diễn đàn này.
Bạn không thể xóa bài của bạn trong diễn đàn này.
Bạn không thể sửa bài của bạn trong diễn đàn này.
Bạn không thể tạo bình chọn trong diễn đàn này.
Bạn không thể bỏ phiếu bình chọn trong diễn đàn này.