2012-05-02 8 views
8

Grałem z wykorzystaniem klienta-klienta, aby uzyskać dostęp do aplikacji szyny, którą napisałem. Napisałem szybki skrypt, aby się zalogować i wysłać prośbę o wpis. Wszystko działa, ale musiałem pracować nad faktem, że żaden autentyczność_token nie jest obsługiwany, jeśli poprosisz o formularz w jsonie. Musiałem zrobić regularne żądanie HTML w innym uzyskać autentyczność_token, a następnie uwzględnione to w json podałem jako część mojego postu. Zasadniczo mam szybki jest brudny skrypt jak poniżejUzyskiwanie tokenów csrf dla żądań postów json do aplikacji szyn

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}) 

Istnieje możliwość, aby wyłączyć ochronę CSRF dla żądań json, ale raczej nie zrobić. Mógłbym pójść na trasę zmechanizowaną lub coś podobnego i wtedy nie martwiłbym się o żądania JSON z CSRF, ale chciałem po prostu zagrać z robieniem tego z klientem-klientem.

Chyba jestem ciekawy, czy wiem istnieje powód, dla którego nie ma mowy o autentyczności dla zgłoszeń json i zastanawiam się również, czy istnieje lepszy sposób na rozwiązanie problemu z tokenem niż dość hackowskie podejście, które tu podjąłem

Odpowiedz

8

Umieść poniższy kod w swojej aplikacji kontroler:

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

I wywołaj tę metodę za pomocą before_filter.

Aby uzyskać więcej informacji sprawdź: http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html

I sprawdzić ten problem w szynach: https://github.com/rails/rails/issues/3041

+1

Dzięki za odpowiedź swati, wygląda na przydatne. Chyba jednak starałem się uniknąć wyłączania czeków CSRF. Po prostu wydaje mi się to trochę dziwne, że szyny obsługują formularze json, które nie zawierają żadnego tokena, a następnie sprawdzają token. Czy miałoby sens tylko podawanie formularzy JSON z dołączonym tokenem, a nie wyłączanie sprawdzania zawartości JSON? – Conor

+0

Witamy ... tak, to tylko sposób na obejście problemu z tokenem CSRF. Jeśli chcesz przekazać token za pomocą żądania JSON, możesz użyć nagłówka takiego jak: nagłówki: { "Token X-CSRF": "<% = form_authenticity_token.to_s%> ' } – swati

+0

sprawdź: 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

w twojej app/views/products/new.json.jbuilder, dodać to:

json.authenticity_token form_authenticity_token 

To będzie wstawić kluczową "authenticity_token" z wartości bytu token, więc w swoim json_response otrzymasz również token. Idea z this answer.