繁体   English   中英

设计如何在登录后重定向到不同的页面(基于某些参数)?

[英]Devise how to redirect to different page (based on some parameter) after sign in?

在我的应用程序中,我有两个来自两个控制器的不同登录表单,它们都将通过 Devise::SessionsController 登录,问题是在成功登录(或失败)后,我需要重定向到特定于控制器的不同页面。 我怎样才能做到这一点。 我目前在我的 Devise::SessionsController 中有这个

class SessionsController < Devise::SessionsController
    def create
        resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
        return sign_in_and_redirect(resource_name, resource)
      end

      def sign_in_and_redirect(resource_or_scope, resource=nil)
        scope = Devise::Mapping.find_scope!(resource_or_scope)
        resource ||= resource_or_scope
        sign_in(scope, resource) unless warden.user(scope) == resource
        redirect_to dashboard_path
      end

      def failure      
        redirect_to index_path
      end
end

在应用程序控制器中

  before_filter :store_location
  def store_location
    unless params[:controller] == "devise/sessions"
      url = #calculate the url here based on a params[:token] which you passed in
      session[:user_return_to] = url
    end
  end

  def stored_location_for(resource_or_scope)
    session[:user_return_to] || super
  end

  def after_sign_in_path_for(resource)
    stored_location_for(resource) || root_path
  end

如果有人仍在寻找解决方法。 我能够通过以下方式解决这个问题:

首先,创建一个继承自Devise::SessionsController的 Sessions 控制器

class SessionsController < Devise::SessionsController

  def new
    get_pre_login_url(request.referer)
    super
  end

  def create
    @@referer_url
    super
  end

private

  def get_pre_login_url(url)
    @@referer_url = url
  end

  def after_sign_in_path_for(resource)
    # @@referer_url
    sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'http')
    if @@referer_url == sign_in_url
      super
    else
      stored_location_for(resource) || @@referer_url || root_path
    end
  end

end

你会注意到我正在设置一个类变量( @@variable_name ),我并不热衷于此,但这是我在尝试各种其他方法来解决这个问题 4 小时后想出的。 我也尽量小心不要过多地使用 Devise 的控制器,不要使用super并且只包括我关心的动作。

接下来,在路由中,您现在可以将设计的默认值指向上面的控制器。 对于devise_for ,您不需要完全像下面devise_for ,只需要引用controllers: { sessions: "sessions" }的部分controllers: { sessions: "sessions" }

MyPortfolio::Application.routes.draw do

  devise_for :users, path_names: { sign_in: "login",
                                   sign_out: "logout" },
                    controllers: { omniauth_callbacks: "omniauth_callbacks",
                                   sessions: "sessions" }

  resources :posts do
    resources :comments
  end

  resources :projects do
    resources :comments
  end

  resources :users

  root :to => 'home#index'

  get 'login' => 'devise/sessions#new'
  get 'about_me' => 'about#index'
end

它可能不是 DRYest 解决方案,但它是我能够想出的唯一一个将重定向指向原始页面而不是 root 或无限循环的解决方案。

您可以通过在控制器中定义after_sign_in_path_for方法来完成此操作,您可以在其中自定义此重定向路径。

以下是更全局的解决方案,但可以在您的情况下使用。 它使用 attr_accessor。 after_sign_in_path_for操作不需要额外的参数,也不需要类变量。

class User < ActiveRecord::Base
  attr_accessor :redirect_to
end

然后,使用专用的 session_controller 文件(按照 Devise 的建议覆盖),复制粘贴原始设计操作并在 respond_with 之前添加行resource.redirect_to = sign_in_params[:redirect_to] 将新重定向添加到after_sign_in_path_for操作并添加:redirect_to参数以设计允许的登录参数。

# app/controllers/devise/sessions_controller.rb

class Users::SessionsController < Devise::SessionsController
  before_filter :configure_sign_in_params, only: [:create]
  
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message!(:notice, :signed_in) if is_flashing_format?
    sign_in(resource_name, resource)

    # set redirect_to
    resource.redirect_to = sign_in_params[:redirect_to]

    yield resource if block_given?
    respond_with resource, location: after_sign_in_path_for(resource)
  end

  # set url to redirect_to url if present
  def after_sign_in_path_for(resource_or_scope)
    return resource_or_scope.redirect_to if resource_or_scope.redirect_to.present? && !resource_or_scope.respond_to?(:devise_scope)
    stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
  end

  # add redirect_to to devise signin allowed params
  def configure_sign_in_params
    devise_parameter_sanitizer.for(:sign_in) << :redirect_to
  end

end

最后,更新您的视图以设置redirect_to url 的隐藏参数

# app/views/users/sessions/new.html.haml
# from params in url
<% if (param_redirect_to = params[:redirect_to]).present?
  <%= f.hidden_field :redirect_to, value: param_redirect_to %>
<% end %>
# or hardcoded if you have 2 sign-in forms
<%= f.hidden_field :redirect_to, value: 'your custom redirect url' %>

成功签名后, GET http://localhost:3000/login?redirect_to=www.test.com会将您的用户重定向到www.test.com

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM