2016-12-07 56 views
9

サインインはChromeでうまく動作しますが、Safariでは動作しません(または他のWebkitブラウザを想定しています)。あなたがサインインした後、私は(「あなたが望んでいた変更が拒否されたたぶん、あなたは、あなたがアクセス権を持っていなかった何かを変更しようとしました。」)は、このエラーメッセージが表示されます。SafariでRails/Deviseサインインが動作しない(422/CSRFエラー)

The change you wanted was rejected. Maybe you tried to change something you didn't have access to.

私のHerokuのログによると、

2016-12-07T14:14:23.778153+00:00 app[web.1]: Can't verify CSRF token authenticity 
2016-12-07T14:14:23.778899+00:00 app[web.1]: Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms) 
2016-12-07T14:14:23.785544+00:00 app[web.1]: 
2016-12-07T14:14:23.785547+00:00 app[web.1]: ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): 

私は適切なCSRFトークンを送信していると思われますが、何かが誤動作しているようです。これは私の現在のapplication_controller.rbです:

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 

    after_action :flash_to_headers 

    # this is so that json requests don't redirect without a user 
    before_action :authenticate_user! 
    # before_action :authenticate_user!, unless: request.format == :json 
    # before_action :user_needed, if: request.format == :json 

    before_action :set_paper_trail_whodunnit 
    before_action :set_global_search_variable 


    def set_global_search_variable 
    @q = Person.ransack(params[:q]) 
    end 

    def user_needed 
    unless current_user 
     render json: { 'error' => 'authentication error' }, status: 401 
    end 
    end 



    def flash_to_headers 
    return unless request.xhr? 
    response.headers['X-Message'] = flash_message if flash_message 
    response.headers['X-Message-Type'] = flash_type.to_s if flash_type 
    flash.discard # don't want the flash to appear when you reload page 
    end 

    private 

    def flash_message 
     [:error, :warning, :notice].each do |type| 
     return flash[type] unless flash[type].blank? 
     end 
     nil 
    end 

    def flash_type 
     [:error, :warning, :notice].each do |type| 
     return type unless flash[type].blank? 
     end 
     nil 
    end 

null_sessionからprotect_from_forgery with:を変更するだけで、ログイン画面に戻るの無限ループが発生します。)

This questionは、同様の問題を参照していますが、工夫の複雑化を議論していません。おそらくDeviseがこの問題を処理していると思われますが、何らかの形でここでは働いていません。 these answersの多くは年を取っているので、今日どのように関連性があるのか​​分かりません。

また、実際のDevise Githubリポジトリのバグを探してみましたが、私はこれらのスレッドの提案をどこにも持っていないようです。アプリケーションコントローラを編集するための提案はたくさんありますが、多くの場合アプリ全体がクラッシュするようです。

このアプリはRuby 2.2.5とRails 4.2.7.1を実行します。 Rails 5へのアップデートはこの問題の解決に役立つでしょうか?

adminアカウントを作成するための既存の(おそらくハッキーな)上書きもあります。その人はDeviseを介してサインアップし、次にシェルでapprovedという別のフィールドを使って管理者アクセスを手動で与えられます。それが関連しているかどうかはわかりません。

アプリは見てみたい人のために、GitHubの上にある: https://github.com/yamilethmedina/kimball

+0

「before_action:authenticate_user!」メソッドの外観はどうですか? –

+0

@AlexanderLunaその方法はどこにありますか?アプリケーションコントローラのその部分は 'before_action:authenticate_user!'の唯一のインスタンスですが、プロジェクトにはいくつかの 'skip_before_action:authenticate_user!'インスタンスがあります。 –

+0

どこにあるかはわかりません。あなたはそれをそこに置くので、あなたは知る必要があります。私が尋ねる理由は、コントローラがリクエストを受け取る前に毎回呼び出されるからです。 –

答えて

6

結局のところ、私の問題はthis answerにより解決しました。結局のところ、アプリケーションコントローラにはなかったが、config/initializers/session_store.rbにあった。

はこれだった私の最初の session_store:さらなる研究をやって、私はこの提案を見つけた時には

Logan::Application.config.session_store :cookie_store, key: '_cutgroup_session', secure: (Rails.env.production? || Rails.env.staging?)

Rails.application.config.session_store :cookie_store, key: "_rails_session_#{Rails.env}", domain: all

これはまだ動作しませんでした。ただし、ログに401エラー(422ではなく)が表示され、上記のスクリーンショットを表示するのではなく、ログインページにリダイレクトされます。

最後に、Rails.application.config.session_store :cookie_store, key: "_rails_session_#{Rails.env}"の末尾からdomain: all部分を削除しました(Safariのクッキーはブラウザのどこからでもブロックされませんでした)。今、私はプロジェクトがHerokuに配備されたときにログインすることができます。

賞金は重い負担でしたが、少なくともコメント投稿者が私の考えを明確にして解決策を見つけるのを手伝ってくれました。他の誰かがこの質問に出くわして、より良いものを思いついたら、私は代わりにそれをupvoteしますが、私は今それを持っていると思います。

+0

この部分は私のために関連する問題を解決します: 'key:" _rails_session _#{Rails.env} "'キーを開発と生産のために別の名前に設定することで、実際に私のマシン上の両方の環境で同じブラウザを奇妙なエラーなしで使用できることを意味します。 – Phil

1

試してみてください。

コントローラ/ application.rb

protect_from_forgery with: :null_session 

と あなたのデバイスコントローラを無効に

sessions_controller.rb

class Users::SessionsController < Devise::SessionsController 
skip_before_filter :verify_authenticity_token, :only => [:destroy] 
end 
+0

お返事ありがとうございます!しかし、アプリケーションコントローラの設定を ':null_session'に変更することは、偽造を許して保護を無効にするため、不適切であると聞いています。それは私のためにも機能しませんでした(ただし、ここで指定されたDeviseコントローラを上書きしなくても) –

関連する問題