2015-05-21 11 views
6

Tôi đang sử dụng Mẫu mã đồng bộ hóa cho các biểu mẫu chuẩn (useToken = true) nhưng tôi không thể tìm thấy bất kỳ phương pháp được đề xuất nào để xử lý vấn đề này trên AJAX.Grails - Có cách nào được khuyến nghị xử lý các cuộc tấn công CSRF trong các biểu mẫu AJAX không?

EDIT

Kể từ khi gửi bài này, tôi đã lăn giải pháp của riêng tôi kết hợp Grails mẫu hiện từ trên cao.

Trong jQuery ajax tôi đăng toàn bộ biểu mẫu (bao gồm các trường bị ẩn SYNCHRONIZER_TOKEN và SYNCHRONIZER_URI được chèn của Grails) sao cho kết thúc withForm có thể hoạt động như mong đợi trong bộ điều khiển.

Vấn đề là, khi trả lời thành công, không có bộ mã thông báo mới (vì trang không được tải lại và thẻ g: form không được gợi lên) và vì vậy tôi làm điều này theo cách thủ công trong bộ điều khiển gọi vào cùng thư viện g: biểu mẫu taglib, và trả về nó trong phản hồi ajax, và sau đó đặt lại giá trị trường ẩn. Xem dưới đây:

var formData = jQuery("form[name=userform]").serializeArray(); 

$.ajax({ 
    type: 'POST', 
    url: 'delete', 
    data: formData, 
    success: function (data) { 
     // do stuff 
    }, 
    complete: function (data) { 
     // Reset the token on complete 
     $("#SYNCHRONIZER_TOKEN").val(data.newToken); 
    } 
}) 

trong Bộ điều khiển:

def delete(String selectedCommonName) { 

    def messages = [:] 
    withForm { 
     User user = User.findByName(name) 

     if (user) { 
      userService.delete(user) 
      messages.info = message(code: 'user.deleted.text') 

     } else { 
      messages.error = message(code: 'user.notdeleted.text') 
     } 
    }.invalidToken { 
      messages.error = message(code: 'no.duplicate.submissions') 
    } 
    // Set a new token for CSRF protection 
    messages.newToken = SynchronizerTokensHolder.store(session).generateToken(params.SYNCHRONIZER_URI) 
    render messages as JSON 
} 

bất cứ ai có thể xác định nếu tôi đã vô tình giới thiệu một lỗ hổng bảo mật trong các giải pháp trên. Nó có vẻ phù hợp với tôi nhưng tôi không thích tay lăn bất cứ điều gì để làm với an ninh.

Trả lời

0

Rất tốt!

IMO, bạn nên đặt lại mã thông báo cùng một lúc.

SynchronizerTokensHolder.store(session).resetToken(params.SYNCHRONIZER_URI)

và nếu bạn có nhiều hình thức trong cùng một trang, xác định một biến để giữ thẻ trở về từ mỗi yêu cầu ajax.

btw, tại sao bạn không tự triển khai mẫu mã thông báo?

  • Tạo mã thông báo, ví dụ: UUID.randomUUID().toString() và lưu nó vào phiên có url làm khóa.
  • Kiểm tra và đặt lại mã thông báo tại hành động bài đăng.
+0

Thực ra, tôi đã sửa đổi việc triển khai này khi gửi lại mã thông báo cho yêu cầu tiếp theo có nghĩa là kẻ tấn công có một số kiến ​​thức cơ bản về triển khai thực hiện Mẫu đồng bộ hóa Grails sẽ có thể khai thác thành công. Vì vậy, tôi đã duy trì việc triển khai ở trên để ngăn chặn việc gửi biểu mẫu trùng lặp và tăng cường nó với giải pháp phạm vi phiên của riêng tôi tạo UUID của riêng tôi theo cách tương tự như bạn đã đề cập ở trên. – dre

+0

Tôi hiểu. Có lẽ bạn nên suy nghĩ về việc đặt lại mã thông báo trong 'complete' thay vì' success'. Trong dự án của tôi, có tấn truy vấn ajax trong cùng một trang, vì vậy tôi nối thêm và đặt lại mã thông báo trong ajaxSend và ajaxStop trên toàn cầu. – Yang

+0

Có, điểm tốt khi thực hiện nó trong * hoàn thành * thay vì * thành công *. Để thực hiện của riêng tôi, tôi tạo ra các mã thông báo và thêm vào phiên ngay sau khi bạn nhấn bộ điều khiển. Tôi không thấy lợi thế của việc tái sinh liên tục, không chắc ai đó sẽ đoán nó trong bất kỳ khoảng thời gian hợp lý nào. Rõ ràng khi người dùng rời đi và trở lại trang, một trang mới sẽ được tạo lại. – dre

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