2011-09-01 38 views
10

đây vấn đề của tôi,Rails 3.1 - CSRF bị bỏ qua?

Tôi đã có một đường ray 3.1 ứng dụng và tôi đang cố gắng để thực hiện một yêu cầu ajax nhưng tôi nhận được thông điệp cảnh báo "CẢNH BÁO: Không thể xác minh tính xác thực CSRF thẻ" ...

Bên trong bố trí của tôi, tôi đã có những phương pháp helper "csrf_method_tag", và tôi thêm dòng sau mã javascript (không biết nếu nó thực sự cần thiết hay không):

$.ajaxSetup({ 
    beforeSend: function(xhr) { 
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')); 
    } 
}); 

My Gemfile chứa đá quý jquery-rails (> = 1.0.12) và tôi yêu cầu jquery & jquery-ujs ở đầu ứng dụng.js của tôi.

Ngay cả khi đó, thông báo vẫn xuất hiện. Tôi đã quên một cái gì đó?

Cảm ơn sự giúp đỡ của bạn.

+0

có cùng sự cố - và sau khi đăng nhập, tôi bị đăng xuất nếu tôi thay đổi các trang (sử dụng đá quý có thể kết nối và rpx có thể kết nối). Hãy cho chúng tôi biết nếu bạn giải quyết vấn đề này – Plattsy

+0

Có phải cookie giống nhau được gửi trong tiêu đề trên yêu cầu AJAX như đã được gửi trên yêu cầu đã tải trang yêu cầu không? Mã thông báo CSRF được xác thực trong bản giao hưởng với phiên hiện tại, được duy trì trong tiêu đề khác (sẽ được gửi tự động nhưng có thể không nằm trong trường hợp của bạn). –

+0

Nhìn vào câu trả lời của tôi ở đây: http://stackoverflow.com/questions/15239818/iframe-causes-cant-verify-csrf-token-authenticity-n-rails/15869772#15869772 – tinker

Trả lời

7

Điều gì làm việc cho tôi - khi làm việc không có biểu mẫu - là bao gồm kết quả của <%= form_authenticity_token %> trong tải trọng dữ liệu ajax. Vì vậy, tôi làm điều gì đó giống như những gì đã được đề xuất bởi tehprofessor trong html:

<input id="tokentag" type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" /> 

sau đó trong javascript:

tokentag = $('#tokentag').val() 
submitdata = { "authenticity_token": tokentag, ...+whatever else you need to include+...} 

sau đó gọi các $.ajax với submitdata.

7

Có thể bạn thậm chí không cần mã này trong mã của mình. Đá quý jquery-rails tự động đặt mã thông báo CSRF trên tất cả các yêu cầu Ajax theo mặc định.

+0

Tôi biết, nhưng ngay cả khi xóa javascript mã, mã thông báo CSRF dường như vẫn bị bỏ qua… –

+0

Bạn có đang sử dụng các trình trợ giúp chuẩn 'form_for' và' form_tag' hay bạn đang sử dụng các thẻ HTML '

' của riêng mình? –

+0

Tôi đang sử dụng không có biểu mẫu ... Tôi sử dụng các yêu cầu để cập nhật partials hoặc để nhận được một số JSON. –

0

Bạn đã thử sử dụng phần tử biểu mẫu ẩn với mã thông báo xác thực chưa?

<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token>" /> 

Tôi đã gặp lỗi tương tự và đã giải quyết được lỗi đó. Đó là vì tôi không sử dụng những người trợ giúp được tạo sẵn ...

+0

Không, vẫn không hoạt động… Tôi phải khắc phục sự cố này trước cuối tuần, tôi cho bạn biết nếu tôi tìm thấy điều gì đó… –

9

Tôi gặp sự cố tương tự chính xác này. Tôi đã cố gắng để bắt một sự kiện javascript (you_tube player hoàn thành) và Ajax trở lại máy chủ của tôi để cho tôi biết. Tôi đã nhận được:

WARNING: Can't verify CSRF token authenticity

bất cứ khi nào cuộc gọi jQuery ajax nhấn máy chủ của tôi. Tôi đã thêm sửa mã của bạn ở trên

$.ajaxSetup({ 
    beforeSend: function(xhr) { 
     xhr.setRequestHeader('X-CSRF-Token', 
          $('meta[name="csrf-token"]').attr('content')); 
    } 
}); 

và hoạt động tốt. Tôi nghĩ rằng sự khác biệt duy nhất là trong cách bố trí của tôi, tôi có

<%= csrf_meta_tags %> 

và không csrf_method_tag ​​như bạn đề cập trong bài gốc của bạn.
Cảm ơn bạn đã khắc phục sự cố, nó đã ở trong bài đăng gốc.

+2

** Vui lòng _don't_ sử dụng chữ ký hoặc khẩu hiệu trong bài đăng của bạn. ** Đọc [ mục FAQ (http://stackoverflow.com/faq#signatures) để biết thêm thông tin. Cảm ơn! –

0

Một lý do có thể là bạn thực hiện cuộc gọi AJAX trước khi tài liệu được tải, vì vậy JQuery không thể nhận được mã thông báo CSRF.

1

Chỉ cần thực hiện trực tiếp cuộc gọi AJAX của bạn và nó sẽ hoạt động bình thường!

$.ajax({ 
      type: //method, 
      beforeSend: function(xhr){ 
       xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')) 
      }, 
      url: //parameter, 
      dataType: 'html', 
      success: function(data, textStatus, jqXHR) { 
       // some code 
      } 
    }); 
0

Vấn đề là bạn cần phải lấy một thẻ mới sau khi một yêu cầu Ajax POST bởi vì một khi một mã thông báo được sử dụng nó được không còn giá trị. Đây là đoạn mã để làm điều này:

Trong đường ray bất cứ khi nào trả lời POST được gửi thêm các thông số này để phản ứng:

def someMethod: 
    result[:csrfParam] = request_forgery_protection_token 
    result[:csrfToken] = form_authenticity_token 
    render :json => result 
end 

Bây giờ ở phía JS, trong hàm thành công của mỗi phương thức POST bạn có thể gọi hàm này:

var setCsrfToken = function(param, token) { 
    if(param == null || token == null) { 
     console.error("New CSRF param/token not present"); 
    } 
    $("input[name='" + param + "']").val(token); 
} 

như thế này:

setCsrfToken(result["csrfParam"], result["csrfToken"]); 

chức năng này sẽ thiết lập lại tất cả các tham số authenticity_token trong tất cả các biểu mẫu POST để yêu cầu tiếp theo có một mã thông báo hợp lệ. Bạn cần đảm bảo điều này xảy ra trong mọi cuộc gọi POST, nếu không bạn sẽ tiếp tục phải đối mặt với vấn đề này.

Ngoài ra, CSRF không phải để ngăn chặn nhấp chuột, đó là một cuộc tấn công riêng biệt, nơi một trang web khác có thể khiến người dùng nhấp vào liên kết thực thi hành động trên trang web của bạn với phiên của người dùng.