25

这里我使用 Devise Gem 进行身份验证。如果有人想在没有登录的情况下打开页面,那么它会重定向到登录页面,并在登录后返回用户尝试打开的页面。我使用重定向循环和 Devise after_sign_in_path_for链接来解决我的问题,但它对我不起作用。

 def after_sign_in_path_for(resource)
   params[:next] || super 
 end

它不会将我重定向回我要打开的页面。例如:如果我要打开“127.0.0.1:3000/post/2/edit”,登录后不会返回这个页面。

4

8 回答 8

44

寻找的最佳资源是官方 repo/wiki/issues,然后是 SO。您找到的答案已过时。

这是答案: https://github.com/plataformatec/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up, -更新

只需在 ApplicationController中为 devise > 3.2.1 版本添加以下内容:

    # This example assumes that you have setup devise to authenticate a class named User.
class ApplicationController < ActionController::Base
  before_action :store_user_location!, if: :storable_location?
  # The callback which stores the current location must be added before you authenticate the user 
  # as `authenticate_user!` (or whatever your resource is) will halt the filter chain and redirect 
  # before the location can be stored.
  before_action :authenticate_user!

  private
    # Its important that the location is NOT stored if:
    # - The request method is not GET (non idempotent)
    # - The request is handled by a Devise controller such as Devise::SessionsController as that could cause an 
    #    infinite redirect loop.
    # - The request is an Ajax request as this can lead to very unexpected behaviour.
    def storable_location?
      request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
    end

    def store_user_location!
      # :user is the scope we are authenticating
      store_location_for(:user, request.fullpath)
    end
end

然后在登录后重定向,你必须重写这个方法:

def after_sign_in_path_for(resource_or_scope)
  stored_location_for(resource_or_scope) || super
end
于 2013-04-11T08:53:34.743 回答
29

您不需要所有这些代码。设计(作为最新版本)已经为您保存了位置。

只需使用这个:

def after_sign_in_path_for(resource)
  request.env['omniauth.origin'] || stored_location_for(resource) || root_url
end

这会将用户重定向到最新的omniauth.source,或stored_location,最后一种情况是root url。

我以为我需要创建该方法,但 Devise 已经做到了。

来源:https ://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in

于 2014-02-07T16:26:23.190 回答
7

Devise 4开始,它对我来说无缝工作:

只要您使用 devise 存储当前页面的位置,Devise 就会在登录和注册时自动重定向 store_location_for(resource)。为此,请编辑您的 ApplicationControllerin app/controllers/application_controller.rb。添加:

# saves the location before loading each page so we can return to the
# right page. If we're on a devise page, we don't want to store that as the
# place to return to (for example, we don't want to return to the sign in page
# after signing in), which is what the :unless prevents
before_filter :store_current_location, :unless => :devise_controller?

private
  # override the devise helper to store the current location so we can
  # redirect to it after loggin in or out. This override makes signing in
  # and signing up work automatically.
  def store_current_location
    store_location_for(:user, request.url)
  end

将以下内容添加ApplicationController到进行注销重定向:

private
  # override the devise method for where to go after signing out because theirs
  # always goes to the root path. Because devise uses a session variable and
  # the session is destroyed on log out, we need to use request.referrer
  # root_path is there as a backup
  def after_sign_out_path_for(resource)
    request.referrer || root_path
  end
于 2017-01-23T04:01:52.173 回答
6

正如官方文档中所指出的,更简单的解决方案是将其简单地添加到您的application_controller.rb

class ApplicationController < ActionController::Base


private

# If your model is called User
def after_sign_in_path_for(resource)
  session["user_return_to"] || root_path
end

重要说明(我也忽略了这一点)是,要使其正常工作,您需要authenticate_user!在控制器的before_action:. 这将在 Devise 中调用store_location_foravailable out of the box ,其余的由 中的上述代码处理,从而无需重写代码来保存请求的 url。application_controller.rb

于 2017-04-05T13:06:52.087 回答
3

如果您的登录表单有自己的页面,而不是例如每个页面标题中的登录表单,这里的一些其他解决方案可能不起作用。登录后,用户需要返回页,而不仅仅是一页。

Devise 有一个很好的 How To on Redirecting back to the current page after sign in, sign out, update,下面的代码来自于它。

将原始 URL 存储在会话中是最佳选择。除了解决上述返回页的问题外,“许多浏览器不发送 [the request.referer] 标头。因此,实现此功能的唯一可靠的跨浏览器方法是使用会话。”

在会话中存储 URL 时,重要的是不要存储任何 POST、PUT 或 DELETE 请求的 URL,也不要存储任何 XHR 请求,即用户实际上无法重定向到的任何内容。

请注意,退出后,用户的会话被破坏,因此存储的 URL 消失了。在这种情况下,用户可以被送回request.referer。这似乎是可以接受的,因为大多数网站在每个页面上都有一个退出链接,因此返回引荐来源网址实际上会起作用。

class ApplicationController < ActionController::Base
  before_action :store_user_location!, if: :storable_location?
  before_action :authenticate_user!

  private
    def storable_location?
      request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
    end

    def store_user_location!
      store_location_for(:user, request.fullpath)
    end

   def after_sign_in_path_for(resource_or_scope)
     stored_location_for(resource_or_scope) || super
   end

   def after_sign_out_path_for(resource_or_scope)
     request.referrer || super
   end
end
于 2017-12-14T22:39:30.040 回答
0

我也有同样的疑问,发现了这个,也试试

def after_sign_in_path_for(resource_or_scope)
  session.fetch 'user_return_to', admin_root_path
end
于 2013-11-28T00:03:44.690 回答
0

无需在 Devise 4.4.3 中定义新方法。直接调用方法DeviseController#after_sign_in_path_for即可。

像这样的代码:

  class YourController < DeviseController

    # ... 
    if manager.valid_password? params[:manager][:password]
      sign_in manager

      # call this method directly , if your controller extends DeviseController
      redirect_to after_sign_in_path_for(manager), notice: 'welcome!'
    end

此外,如果您使用自定义登录方法并使用 DeviseController,则不得使用此代码:

# this method will login automatically, in most cases this method is 
# useless and misleading.  
prepend_before_action :allow_params_authentication!, only: :create
于 2019-08-11T01:20:46.493 回答
0

gem 'devise', '~> 4.4.0'

  1. 创建 session_controller.rb:class SessionsController < Devise::SessionsController

  2. 添加以下内容(如果您的登录网址不是 /users,请修改正则表达式)

    def before_login
      session[:previous_url] = request.fullpath unless request.fullpath =~ /\/users/
    end
    
    def after_login
      session[:previous_url] || root_path
    end
    

请注意,如果您有 /users/dashboard 或 /users 下的其他位置,这将不起作用。可能想要更具体地使用正则表达式。

于 2018-04-26T15:15:29.200 回答