Rails 4 Orijinallik Simgesi


198

Bazı özgünlük belirteci sorunlarıyla karşılaştığımda yeni bir Rails 4 uygulaması (Ruby 2.0.0-p0'da) üzerinde çalışıyordum.

( respond_toClass yöntemini kullanarak ) json yanıt veren bir denetleyici yazarken , kullanarak bir kayıt oluşturmaya çalıştığımda özel durumlar createalmaya başladığım eylem var .ActionController::InvalidAuthenticityTokencurl

-H "Content-Type: application/json"Verileri ayarladığımdan emin oldum ve verileri ayarladım -d "<my data here>"ama hala şans yok.

Aynı denetleyiciyi Rails 3.2 (Ruby 1.9.3'te) kullanarak yazmaya çalıştım ve hiçbir şekilde özgünlük belirteci problemim yok. Etrafı araştırdım ve Rails 4'te özgünlük belirteçlerinde bazı değişiklikler olduğunu gördüm. Anladığım kadarıyla artık otomatik olarak formlara eklenmiyorlar mı? Bunun bir şekilde HTML dışı içerik türlerini etkilediğini düşünüyorum.

HTML formu istemeden, özgünlük belirtecini kapmadan ve daha sonra bu belirteçle başka bir istekte bulunmadan bu sorunu çözmenin bir yolu var mı? Yoksa tamamen bariz bir şeyi tamamen mi kaçırıyorum?

Düzenleme: Sadece bir şey değiştirmeden bir iskele kullanarak yeni bir Rails 4 uygulamasında yeni bir kayıt oluşturmayı denedim ve sanırım yaptığım bir şey değil.

Yanıtlar:


277

Ben sadece anladım. (Yeni) varsayılanı değiştirdim

protect_from_forgery with: :exception

için

protect_from_forgery with: :null_session

yorumuna göre ApplicationController.

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.

Farkı request_forgery_protecton.rb, aşağıdaki satırların kaynağına veya daha spesifik olarak bakarak görebilirsiniz :

In Raylar 3.2 :

# This is the method that defines the application behavior when a request is found to be unverified.
# By default, \Rails resets the session when it finds an unverified request.
def handle_unverified_request
  reset_session
end

In Raylar 4 :

def handle_unverified_request
  forgery_protection_strategy.new(self).handle_unverified_request
end

Hangi arayacak aşağıdaki :

def handle_unverified_request
  raise ActionController::InvalidAuthenticityToken
end

20
: Seçeneğini tümüyle birlikte kaldırabilirsiniz,: null_session varsayılan değerdir
Casey

6
JSON dışı çağrılar ve JSON çağrıları (diğer adıyla API çağrıları) için boş oturum için istisna kullanmanın bir yolu var mı?
James McMahon

@JamesMcMahon Biçimi before_actionkontrol eden ve isteğin doğrulanıp doğrulanmadığını kendiniz yazabilirsiniz . Koşullar belirlemek için yerleşik bir yöntem bilmiyorum.
alexcoco

1
4.1.6 raylarında, skip_before_action :verify_authenticity_tokenbu işi yapmak için API'mın uygulama denetleyicisini de belirtmem gerekiyordu.
Waseem

1
:verify_authenticy_tokenRails 4.2'de artık devre dışı bırakmanız gerekmemelidir . Varsayılan :null_sessionolarak, adından da anlaşılacağı gibi, size oturumu olmayan bir istek verir. Bunun yerine isteği bir API anahtarı aracılığıyla doğrulayabilirsiniz.
lobati

72

CSRF korumasını kapatmak yerine, forma aşağıdaki kod satırını eklemek daha iyidir

<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %> 

ve form oluşturmak için form_for veya form_tag kullanıyorsanız, yukarıdaki kod satırını otomatik olarak forma ekler


9
Bir form oluşturuyorsanız bu iyi bir tavsiye, ancak soru JSON kullanarak API çağrıları yapmakla ilgilidir.
James McMahon

1
Yine de teşekkür ederim, bu gidon kullanırken bir kod yazma hakkında bir soruya cevap verdi!
David Routen

70

Forma aşağıdaki satırı eklemek benim için çalıştı:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

12
gerçekten api çağrıları için geçerli değil
courtsimas

2
Benim durumumda Rails4 kullanıyorum. Formu gönder düğmesini tıklayarak gönderebilirim. Ancak formu JS kodu ile gönderirseniz, bu hata oluşur. Ve bu cevap benim için sorunu çözdü.
Chris.Zou

2
Benim Rails 4.0.8 tabanlı App yazmak =token_tag nilveya (.erb içinde) için yeterliydi<%= token_tag nil %>
jmarceli

1
Simgeyi nil olarak ayarlayarak kimlik doğrulamayı devre dışı bırakıyor musunuz?
Carlos

bunu yapmak güvenli mi?
Angel Garcia

33

Yalnızca bir API uygulamadığınız sürece CSRF korumasını kapatmanın iyi olduğunu düşünmüyorum.

ActionController için Rails 4 API belgelerine bakarken, her denetleyicide veya yöntem bazında sahtecilik korumasını kapatabileceğinizi buldum.

Örneğin, kullanabileceğiniz yöntemler için CSRF korumasını kapatmak için

class FooController < ApplicationController
  protect_from_forgery except: :index

Bunu benim için Rails 4'te yaptı - silmeye çalıştıktan sonra hata oluştu. ^^
zero_cool

9

Aynı sorunla karşılaştım. Denetleyicime ekleyerek düzeltildi:

      skip_before_filter :verify_authenticity_token, if: :json_request?

tanımsız yöntem `` json_request? '' # <SettingsController: 0x000000030a54a8> için, Herhangi bir fikir var mı?
Deano

Orada bir yöntem tanımlamanız gerekir: def json_request? request.format.json? sonu
Jai Kumar Rajput

7

Denedin mi?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }



2

Bu özellikler güvenlik ve sahtecilikten korunma amacıyla eklenmiştir.
Ancak, sorunuzu cevaplamak için bazı girdiler. Bu satırları denetleyici adınızdan sonra ekleyebilirsiniz.

Bunun gibi,

class NameController < ApplicationController
    skip_before_action :verify_authenticity_token

İşte rayların farklı versiyonları için bazı çizgiler.

Raylar 3

skip_before_filter: verify_authenticity_token

Raylar 4 :

skip_before_action: verify_authenticity_token


Bu denetleyici yordamlarını tüm denetleyici yordamları için devre dışı bırakmak isterseniz, application_controller.rb dosyanızdaki protect_from_forgery değerini null_session olarak değiştirebilirsiniz .

Bunun gibi,

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session
end

1

Raylı jQuery kullanıyorsanız, özgünlük jetonunu doğrulamadan yöntemlere giriş yapmaya izin vermekten kaçının.

jquery-ujs jetonları sizin için yönetebilir

Zaten jquery-rails geminin bir parçası olarak sahip olmalısınız, ancak application.js içine eklemeniz gerekebilir.

//= require jquery_ujs

Tüm ihtiyacınız olan bu - ajax çağrınız şimdi çalışmalı

Daha fazla bilgi için bkz. Https://github.com/rails/jquery-ujs



0

Kendi html formunuzu tanımladığınızda, güvenlik nedeniyle denetleyiciye gönderilmesi gereken kimlik doğrulama belirteci dizesi eklemeniz gerekir. Eğer rails form helper oluşturmak için özgünlük belirteci oluşturmak için aşağıdaki gibi form eklenir.

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
  </div>
    ...
</form>

Bu nedenle, sorunun çözümü, authenticity_token alanı eklemek veya güvenlikten ödün vermek yerine ray yardımcıları form yardımcıları kullanmaktır.


1
Cevabınız için teşekkür ederim, ancak bu orijinal soruya cevap vermiyor. Soru, JSON isteklerine yanıt verme hakkında sordu, ancak sıfırdan bir HTML formu için bir çözüm sağlıyorsunuz. JSON istekleri (think API) yaparken, bir HTML formu göndermiyorsunuz ve özgünlük belirtecine kolay erişiminiz olmayabilir.
alexcoco

isteğin içeriği aslında JSON değilse, bu durumda onu ayarlamak istersiniz application/json.
alexcoco

Cevabın tam olarak aradığınız şey olmadığını anlıyorum. Ancak ilgili yanıtı koymanın amacı benzer "Orijinallik Sorunları" arayan kullanıcılara yardımcı olmaktır.
amjad

üzgünüm yanlışlıkla kaldırdım - "İçerik Türü ayarlayabilirsiniz: application / x-www-form-urlencoded yukarıdaki çözüm".
amjad

0

Tüm testlerim iyi çalışıyordu. Ama nedense ortam değişkenimi test etmemeye ayarladım:

export RAILS_ENV=something_non_test

ActionController::InvalidAuthenticityTokenİstisna almaya başladığım için bu değişkeni kaldırmayı unuttum .

Ayarı kaldırdıktan sonra $RAILS_ENVtestlerim tekrar çalışmaya başladı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.