2016-02-15 8 views
7

मुझे रेल उत्पादन में "सीएसआरएफ टोकन प्रामाणिकता सत्यापित नहीं कर सकता" प्राप्त हो रहा है। मेरे प्रश्न हैं:रेल मुझे क्यों दे रहा है "सीएसआरएफ टोकन प्रामाणिकता सत्यापित नहीं कर सकता" त्रुटि?

  1. यह ऐसा क्यों कर रहा है?
  2. मैं इसे कैसे ठीक कर सकता हूं?

यहाँ मेरी Heroku लॉग (कुछ मान उसकी गुमनाम):

2016-02-13T01:18:54.118956+00:00 heroku[router]: at=info method=POST path="/login" host=[MYURL] request_id=[ID STRING] fwd="FWDIP" dyno=web.1 connect=0ms service=6ms status=422 bytes=1783 
2016-02-13T01:18:54.116581+00:00 app[web.1]: Started POST "/login" for [IPADDRESS] at 2016-02-13 01:18:54 +0000 
2016-02-13T01:18:54.119372+00:00 app[web.1]: Completed 422 Unprocessable Entity in 1ms 
2016-02-13T01:18:54.118587+00:00 app[web.1]: Processing by SessionsController#create as HTML 
2016-02-13T01:18:54.118637+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"[BIGLONGRANDOMTOKENSTRING]", "session"=>{"email"=>"[FRIENDSEMAILADDRESS]", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"} 
2016-02-13T01:18:54.119082+00:00 app[web.1]: Can't verify CSRF token authenticity 
2016-02-13T01:18:54.120565+00:00 app[web.1]: 
2016-02-13T01:18:54.120567+00:00 app[web.1]: ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): 
2016-02-13T01:18:54.120569+00:00 app[web.1]: vendor/bundle/ruby/2.2.0/gems/actionpack-4.2.0/lib/action_controller/metal/request_forgery_protection.rb:181:in `handle_unverified_request' 
. 
. 
.etc 

केवल अभिव्यक्ति मैं है के बारे में पता कर रहा हूँ जब मेरे दोस्त उसकी iPhone पर Safari का उपयोग कर 5. उनकी उपयोगकर्ता खाता था प्रवेश करने का प्रयास लगभग 6 महीने पहले बनाया गया। मुझे 99% यकीन है कि उसने उस समय अपने फोन के साथ साइट को ठीक से एक्सेस किया था। तब से उन्होंने लॉग इन नहीं किया है और मुझे लॉगिन/ऑथ कोड में किए गए किसी भी बदलाव से अवगत नहीं है। कल मैंने उसे पहली बार ~ 6 महीने में अपनी साइट पर मारा था और अब उसे सीएसआरएफ त्रुटि मिलती है।

यह समस्या किसी भी अन्य उपयोगकर्ता खाते (जो मुझे पता है) या किसी अन्य डिवाइस पर नहीं होती है। असल में, अपने पुराने आईफोन 4 से अपने खाते में लॉग इन करना ठीक काम करता है।

मेरे पास देव अनुभव का एक सभ्य राशि है लेकिन वेब देव और सब कुछ रेल के लिए बिल्कुल नया है।

class ApplicationController < ActionController::Base 
    # Prevent CSRF attacks by raising an exception. 
    # For APIs, you may want to use :null_session instead. 
    protect_from_forgery with: :exception 
    include SessionsHelper 
end 

आवेदन लेआउट:

यहाँ मैं क्या है है

<!DOCTYPE html> 
<html> 
<head> 
<title><%= full_title(yield(:title)) %></title> 
<meta name="viewport" content="width=device-width,initial-scale=1"> 
<%= stylesheet_link_tag 'application', media: 'all' %> 
<%= javascript_include_tag 'application' %> 
<%= csrf_meta_tags %> 
<%= render 'layouts/shim' %> 
</head> 
<body> 
<%= render 'layouts/header' %> 
<div class="container"> 
<% flash.each do |message_type, message| %> 
<div class="alert alert-<%= message_type %>"><%= message %></div> 
<% end %> 
<%= yield %> 
<%= render 'layouts/footer' %> 
<%= debug(params) if Rails.env.development? %> 
</div> 
</body> 
</html> 

मेरे रहस्य फ़ाइल इस तरह दिखता है:

# Do not keep production secrets in the repository, 
# instead read values from the environment. 
production: 
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 

और मैं के लिए Heroku पर उत्पादन परिवेश वर है secret_key_base।

def log_in(user) 
    session[:user_id] = user.id 
end 

def remember(user) 
    user.remember 
    cookies.permanent.signed[:user_id] = user.id 
    cookies.permanent[:remember_token] = user.remember_token 
end 

यहाँ मैं क्या किया है:
मैं अध्याय के माध्यम से ऊपर/करने के लिए पत्र के लिए Michael Hartl's Rails Tutorial में सब कुछ का पालन करके अपने ऐप्स को विकसित करना शुरू किया 10 सबसे अधिक प्रासंगिक, विशेष रूप से अध्याय 8. है मेरे ऐप सभी सुरक्षा का उपयोग करता है/कुकीज़/उपयोगकर्ता ऑथ सामान ठीक उसी तरह के रूप में। मैं अपने ऐप में कुछ भी नहीं करता ... कोई AJAX या ऐसा कुछ भी नहीं। मैं भी turbolinks yanked।

मेरी परियोजना पिछले 18 महीनों में फैली हुई है, इसलिए मैं 100% सकारात्मक नहीं हूं जिस संस्करण पर मैंने शुरुआत की थी। मुझे पता है कि यह 4.1.एक्स था और यह शायद 4.1.6 था। मुझे यह भी पता नहीं है कि मैंने जिस तारीख को अपग्रेड किया था, लेकिन किसी बिंदु पर जो मैं वर्तमान में चल रहा हूं; 4.2.0।

मैंने सीएसआरएफ + रेल के साथ समस्याओं के बारे में वेब पर केवल हर पोस्ट को पढ़ा है। ऐसा लगता है कि मैंने जो कुछ भी पढ़ा है, उसके कारण कारण और समाधान को AJAX या Devise के साथ करना है, जिसमें से कोई भी मेरे लिए लागू नहीं होता है। iFrame समस्याएं वेब पर एक और आम स्रोत हैं, जिसका मैं न तो उपयोग कर रहा हूं।

मैंने अपने ऐप की पासवर्ड रीसेट सुविधा का उपयोग नहीं किया है। मैंने protect_from_forgery को इसके साथ बदलने की कोशिश की:: reset_session। एकमात्र चीज यह बदलती है रेल अपवाद पृष्ठ अब प्रदर्शित नहीं होता है। लेकिन यह उसे प्रमाणीकरण की आवश्यकता वाले किसी भी पृष्ठ पर जाने नहीं देगा।

get '*path' => redirect('/') 

मैं उसकी कुकीज़/कैश आदि स्पष्ट करने के लिए है क्योंकि मैं अन्य मौजूदा उपयोगकर्ता खातों है कि मैं नहीं चाहता के दर्जनों की जरूरत नहीं है चाहता हूँ: यह सिर्फ इसलिए कि मैं अपने मार्गों में इस लाइन है जड़ तक उसे वापस ले जाता है मैन्युअल रूप से ठीक करने के लिए है।

अक्सर सुझाए गए समाधान सुरक्षा को बंद करने के कुछ रूप हैं, जो मैं स्पष्ट कारणों से नहीं करना चाहता हूं।

कुछ अन्य बातों मैं बदल गया है, लेकिन अभी तक परीक्षण करने के लिए (क्योंकि मैं अपने दोस्त के iPhone करने के लिए आसान पहुँच नहीं है) का मौका नहीं पड़ा है:

मैं session_store.rb में डालें, नाम बदल दिया है:

Rails.application.config.session_store :cookie_store, key: '[NEWNAME]' 

Ran निम्न कमांड:
Heroku रन रेक संपत्ति: स्वच्छ
Heroku रन रेक संपत्ति: precompile

मैं के बारे में शुरू करने हूं गहरी गोताखोरी here, विशेष रूप से धारा 3.

पढ़ने/विचार करने के लिए धन्यवाद। किसी भी सुझाव/विचार/सुझाव/पॉइंटर्स की सराहना की जाएगी!

+0

क्या आप कुछ आक्रामक कैशिंग निर्देशों को नियोजित करते हैं? अर्थात। क्या आपके मित्र का ब्राउज़र पुन: उपयोग करेगा जो अनन्त समाप्ति के कारण स्थानीय रूप से कैश किया गया है? – Raffael

+0

@ रैफेल "कैशिंग" द्वारा मुझे लगता है कि आप कुकी में संग्रहीत किए गए चीज़ों का जिक्र कर रहे हैं (याद रखें, मैं एक प्रमुख वेब देव नोब हूं, इसलिए अगर मैं यहां से हूं तो मुझे आश्चर्य नहीं होगा)। कुकी में संग्रहीत एकमात्र चीज ईमेल और remember_me है। मैं कोई डेटा स्टोर नहीं करता हूं। – davidh

+0

मेरा मतलब कुकीज़ नहीं है लेकिन HTML शीर्षलेख जो ब्राउज़र (और प्रॉक्सी) को बताते हैं कि वे सामग्री को कैसे कैश कर सकते हैं। एक ब्राउज़र कुछ सामग्री के मौजूदा संस्करण के लिए सर्वर से भी नहीं पूछ सकता है अगर इसे डाउनलोड की गई आखिरी चीज़ अभी भी HTML शीर्षकों के अनुसार मान्य है। लेकिन चूंकि आपको इसके बारे में पता नहीं था, इसलिए आपने वहां डिफ़ॉल्ट रूप से बदलाव नहीं किया था। – Raffael

उत्तर

2

this gentleman बाहर निकलता है मेरे जैसा ही मुद्दा था और मेरे लिए काम करने वाले एक रेपो केस बनाने में सक्षम था। अगर मैं सही समझ रहा हूं, तो सफारी पेज को कैश कर रही है लेकिन सत्र को रद्द कर रही है। यह प्रामाणिकता_टोकन मान को मेरे रेल पैराम में वैध दिखने का कारण बनता है लेकिन टोकन को सत्यापित करते समय protect_from_forgery विफल रहता है क्योंकि सत्र को नियुक्त किया गया था।

समाधान फिर दो गुना है: कैशिंग बंद करें और सीएसआरएफ अपवादों को संभालें। यदि आप कैशिंग बंद कर देते हैं तो भी आपको अपवादों को संभालने की आवश्यकता है क्योंकि कुछ ब्राउज़र (उदा। सफारी) नो-कैश सेटिंग्स का सम्मान नहीं करते हैं। इस मामले में एक सीएसआरएफ मुद्दा उठता है और इसलिए इसे संभालने की आवश्यकता भी होती है।

वैकल्पिक हल मुझे मेरे सभी कुकी और सत्र डेटा की हत्या से CSRF अपवाद को संभालने के लिए था के लिए, एक "ओह" संदेश फ्लैश और उन्हें प्रवेश पृष्ठ पर रीडायरेक्ट करते हैं। रीडायरेक्ट एक ताजा ऑथ टोकन खींच देगा जो लॉगिन पोस्ट करते समय सत्यापित करेगा। यह विचार here से आया था:

यह उदाहरण के लिए cookies.permanent साथ, स्टोर उपयोगकर्ता जानकारी के लिए लगातार कुकीज़ का उपयोग करने के लिए आम है। इस मामले में, कुकीज़ को मंजूरी नहीं दी जाएगी और बॉक्स सीएसआरएफ सुरक्षा से बाहर प्रभावी नहीं होगा। आप इस जानकारी के लिए सत्र से एक अलग कुकी स्टोर का उपयोग कर रहे हैं, तो आप को संभाल चाहिए कि क्या यह अपने आप के साथ क्या करना:

rescue_from ActionController::InvalidAuthenticityToken do |exception| 
    sign_out_user # Example method that will destroy the user cookies 
end 

उपरोक्त विधि ApplicationController में रखा जा सकता है और जब बुलाया जाएगा एक CSRF टोकन मौजूद नहीं है या एक गैर GET अनुरोध पर सही नहीं है।

cookies.permanent मैं वास्तव में क्या उपयोग कर रहा था है।

class ApplicationController < ActionController::Base 
    include SessionsHelper 
    protect_from_forgery with: :exception 
    before_filter :set_cache_headers 
    rescue_from ActionController::InvalidAuthenticityToken do |exception| 
    cookies.delete(:user_id) 
    cookies.delete(:remember_token) 
    session.delete(:user_id) 
    @current_user = nil 
    flash[:danger] = "Oops, you got logged out. If this keeps happening please contact us. Thank you!" 
    redirect_to login_path 
    end 

    def set_cache_headers 
    response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" 
    response.headers["Pragma"] = "no-cache" 
    response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" 
    end 
end 

संयोग से, ठीक लागू करने और सत्यापित करने से यह देव में काम करने के बाद, मेरे दोस्त का फोन अभी भी प्रवेश करने के लिए, अलग-अलग व्यवहार के साथ यद्यपि में असमर्थ था: तो मैं इस तरह से ऊपर टिप लागू किया।जांच के बाद मैंने पाया कि उसके आईफोन 5 सफारी सेटिंग्स में "सभी कुकीज़ अवरुद्ध" थीं। इसने अन्य अजीब व्यवहार का कारण बना दिया जिससे यह पता लगाना मुश्किल हो गया कि कौन सा मुद्दा पैदा कर रहा था। टिपऑफ आया जब मुझे एहसास हुआ कि मैं किसी भी ऑनलाइन खाते में लॉग इन करने के लिए अपने फोन का उपयोग नहीं कर सका (जैसे याहू मेल इत्यादि)। अपनी सफारी सेटिंग्स में जाकर और कुकीज को हल करने की इजाजत देता है और अब सब कुछ उसके फोन पर बहुत अच्छा काम करता है (और हर जगह जहां मुझे पता है)।

संबंधित मुद्दे

 संबंधित मुद्दे