6

AJAX リクエストを処理するために Devise (3.1.1) サインイン/サインアップ メソッドを拡張しようとしていますが、確認可能なロジックで行き詰っています。通常、ユーザーがアカウントを確認する前に Devise にサインインすると、「続行する前にアカウントを確認する必要があります」というフラッシュ メッセージとともにログイン画面にリダイレクトされます。Devise がどこで確認を確認し、リダイレクトの決定を行っているかを把握することはできません。

これが拡張session_controllerコードです。成功したログイン試行と失敗したログイン試行に対して正常に機能します。

  # CUSTOM (Mix of actual devise controller method and ajax customization from http://natashatherobot.com/devise-rails-sign-in/):
  def create
    # (NOTE: If user is not confirmed, execution will never get this far...)
    respond_to do |format|
      format.html do 
        # Copied from original create method:
        self.resource = warden.authenticate!(auth_options)
        set_flash_message(:notice, :signed_in) if is_navigational_format?
        sign_in(resource_name, resource)
        respond_with resource, :location => after_sign_in_path_for(resource)
      end                       
      format.js  do
        # Derived from Natasha AJAX recipe:
        self.resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
        sign_in(resource_name, resource)
        return render :json => {:success => true, :token => form_authenticity_token() }, content_type: "application/json" # Need to explicitely set content type to JSON, otherwise it gets set as application/javascript and success handler never gets hit.
      end          
    end

  end

  def failure
    return render :json => {:success => false, :errors => ["Login failed."]}
  end

問題は、ユーザーが未確認の場合、createメソッドがヒットしないことです。リダイレクトは以前のどこかで発生します。つまり、JS に適した方法で処理することはできません。しかし、ソースを調べてみると、確認可能なチェックを行う前のフィルターが見つかりません。確認可能なチェックはどこで行われ、どのように傍受できますか?

4

4 に答える 4

3

@gregates はこれを理解した功績を認められていますが、実際にこれをどのように機能させたかを示したかったのです。

問題は、コントローラー レベルで未確認のユーザーをチェックまたはインターセプトできないことでした。これは、モデル レベルで を使用してチェックされ、active_for_authentication?すぐに Warden の失敗アプリによって処理されるためです。したがって、 への参照は、current_user実行中のコントローラー ロジックをショートさせます。解決策は、独自のカスタム FailureApp を導入し、必要に応じて処理することです。私たちの場合、これは AJAX 認証エラーに対して特別なエラーを発生させることを意味していました。方法は次のとおりです。

最初に、ここで説明されているように、カスタム失敗アプリを作成します:
方法: ユーザーが認証できない場合に特定のページにリダイレクトする · plataformatec/devise Wiki

lib/custom_failure.rb:

class CustomFailure < Devise::FailureApp

  def respond

    # We override Devise's handling to throw our own custom errors on AJAX auth failures,
    # because Devise provides no easy way to deal with them:

    if request.xhr? && warden_message == :unconfirmed
      raise MyCustomErrors::AjaxAuthError.new("Confirmation required. Check your inbox.")
    end

    # Original code:

    if http_auth?
      http_auth
    elsif warden_options[:recall]
      recall
    else
      redirect
    end
  end

end

そして、Warden にカスタムの失敗アプリを使用するように指示します。

config/initializers/devise.rb:

  config.warden do |manager|
    manager.failure_app = CustomFailure
  end

そして、好きなようにカスタムエラーを処理するだけです。この場合、ErrorController が 401 JSON 応答を返すようにしました。

于 2013-11-09T17:24:54.973 に答える