2012-05-02 30 views
8

Tôi đã chơi xung quanh bằng cách sử dụng ứng dụng khách để truy cập ứng dụng đường ray mà tôi đã viết. Tôi đã viết một kịch bản nhanh để đăng nhập và thực hiện một yêu cầu đăng bài. Tất cả mọi thứ đang làm việc nhưng tôi đã phải làm việc vòng thực tế là không có authenticity_token được phục vụ nếu bạn thực hiện một yêu cầu cho một hình thức trong json. Tôi đã phải thực hiện một yêu cầu html thường xuyên trong khác có được authenticity_token và sau đó bao gồm điều này trong json tôi gửi như là một phần của yêu cầu bài viết của tôi. Về cơ bản, tôi có một tập lệnh dơ bẩn nhanh như tập lệnh bên dướinhận mã thông báo csrf cho các yêu cầu bài đăng json tới ứng dụng đường ray

private_resource = RestClient::Resource.new('https://mysite.com') 

params = {:user => {:email => '[email protected]', :password => 'please'}} 
#log in 
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json) 
#get cookie 
cookie = login_response.cookies 
#get json 
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie) 
#another request that returns html form with authenticity token 
response_with_token = private_resource['products/new'].get(:cookies => cookie) 
#extract token 
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value') 
#update cookie 
cookie = response_with_token.cookies 
#populate form and insert token 
form = JSON.parse(json_response) 
form['name'] = "my product" 
form['authenticity_token'] = token 
#submit the request 
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json}) 

Có tùy chọn tắt bảo vệ CSRF đối với các yêu cầu json nhưng tôi không muốn thực hiện điều đó. Tôi có thể đi theo con đường cơ giới hóa hoặc một cái gì đó tương tự và sau đó tôi sẽ không lo lắng về yêu cầu json với CSRF nhưng tôi chỉ muốn chơi xung quanh với công cụ này với khách hàng nghỉ ngơi

Tôi đoán tôi chỉ tò mò muốn biết có một lý do tại sao không authenticity_token được phục vụ cho các yêu cầu json và tôi cũng tự hỏi nếu có một cách tốt hơn để giải quyết vấn đề token hơn là cách tiếp cận khá hacky tôi đã thực hiện ở đây

Trả lời

8

Đặt mã bên dưới vào ứng dụng của bạn bộ điều khiển:

def verified_request? 
    if request.content_type == "application/json" 
     true 
    else 
     super() 
    end 
end 

Và gọi phương thức này bằng cách sử dụng before_filter.

Để biết thêm chi tiết kiểm tra: http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html

Và kiểm tra vấn đề này trong đường ray: https://github.com/rails/rails/issues/3041

+1

Cảm ơn bạn đã trả lời câu trả lời của bạn, có vẻ hữu ích. Tôi đoán mặc dù tôi đã cố gắng tránh chỉ cần tắt các kiểm tra CSRF. Nó chỉ có vẻ hơi lạ với tôi rằng đường ray phục vụ các hình thức json không chứa bất kỳ mã thông báo nào nhưng sau đó kiểm tra mã thông báo. Nó sẽ có ý nghĩa chỉ để phục vụ các hình thức json với một mã thông báo bao gồm thay vì tắt các kiểm tra cho nội dung json? – Conor

+0

chào mừng bạn ... có đó là cách duy nhất để vượt qua vấn đề mã thông báo CSRF. Nếu bạn muốn chuyển mã thông báo với yêu cầu JSON của mình, bạn có thể sử dụng tiêu đề như: tiêu đề: { 'X-CSRF-Mã thông báo': '<% = form_authenticity_token.to_s%>' } – swati

+0

kiểm tra: http: // stackoverflow. com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails http://stackoverflow.com/questions/8503447/rails-how-to-add-csrf-protection-to-forms-created-in -javascript – swati

0

Trong app/views/products/new.json.jbuilder của bạn, thêm này:

json.authenticity_token form_authenticity_token 

này sẽ chèn một chìa khóa "authenticity_token" với giá trị con người mã thông báo, vì vậy trong số json_response bạn cũng nhận được mã thông báo. Ý tưởng từ this answer.

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