2010-02-28 36 views
8

Trang tôi đang xây dựng phụ thuộc rất nhiều vào AJAX. Về cơ bản, chỉ có một "trang" và mọi chuyển dữ liệu được xử lý thông qua AJAX. Kể từ khi bộ nhớ đệm overoptimistic trên phía trình duyệt dẫn đến các vấn đề lạ (dữ liệu không được tải lại), tôi phải thực hiện tất cả các yêu cầu (cũng đọc) bằng cách sử dụng POST - mà lực lượng tải lại.Bảo vệ CSRF trong các yêu cầu AJAX sử dụng MVC2

Bây giờ tôi muốn ngăn trang chống lại CSRF. Với việc gửi biểu mẫu, sử dụng Html.AntiForgeryToken() hoạt động gọn gàng, nhưng trong yêu cầu AJAX, tôi đoán tôi sẽ phải gắn mã thông báo theo cách thủ công? Có bất kỳ thứ gì ngoài hộp có sẵn không?

nỗ lực hiện tại của tôi trông giống như này:

Tôi rất muốn tái sử dụng ma thuật hiện có. Tuy nhiên, HtmlHelper.GetAntiForgeryTokenAndSetCookie là riêng tư và tôi không muốn hack xung quanh trong MVC. Tùy chọn khác là viết một tiện ích mở rộng như

public static string PlainAntiForgeryToken(this HtmlHelper helper) 
{ 
    // extract the actual field value from the hidden input 
    return helper.AntiForgeryToken().DoSomeHackyStringActions(); 
} 

có phần bị hack và để lại vấn đề lớn hơn chưa được giải quyết: Cách xác minh mã thông báo đó? Việc triển khai xác minh mặc định là nội bộ và được mã hóa cứng để sử dụng các trường biểu mẫu. Tôi đã cố gắng viết một chút sửa đổi ValidateAntiForgeryTokenAttribute, nhưng nó sử dụng một AntiForgeryDataSerializer đó là riêng tư và tôi thực sự không muốn sao chép điều đó, quá.

Tại thời điểm này, có vẻ dễ dàng hơn khi đưa ra giải pháp phát triển trong nước, nhưng đó thực sự là mã trùng lặp.

Bất kỳ đề xuất nào về cách thực hiện điều này một cách thông minh? Tôi có thiếu cái gì đó hoàn toàn hiển nhiên?

Trả lời

10

Bạn có thể sử dụng thông thường Html.AntiForgeryToken() helper để tạo ra một lĩnh vực tiềm ẩn ở đâu đó trên trang (không nhất thiết bên trong một hình thức) và bao gồm nó dọc theo yêu cầu ajax:

var token = $('input[name=__RequestVerificationToken]').val(); 
$.post(
    '/SomeAction', { '__RequestVerificationToken': token }, 
    function() { 
     alert('Account Deleted.'); 
    } 
); 

Để xác minh nó ở phía máy chủ:

[AcceptVerbs(HttpVerbs.Post)] 
[ValidateAntiForgeryToken] 
public ActionResult SomeAction() 
{ 
    return View(); 
} 

Nếu bạn có nhiều mã thông báo trên trang của mình, bạn có thể cần phải chỉ định mã nào cần bao gồm. Khi helper hiện tạo ra các lĩnh vực tiềm ẩn với cùng tên rất khó để thực hiện một bộ chọn tốt để bạn có thể đặt chúng nhịp bên trong:

<span id="t1"><%= Html.AntiForgeryToken() %></span> 
<span id="t2"><%= Html.AntiForgeryToken() %></span> 

và sau đó chọn thẻ tương ứng:

var token = $('#t1 input[name=__RequestVerificationToken]').val(); 
+0

Brilliant! Làm việc như một say mê! Tôi không biết các trường được đăng sẽ kết thúc trong 'Request.Form'. 1 cho tuyên bố chọn rất gọn gàng. Chúc mừng! – mnemosyn

Các vấn đề liên quan