这里我使用Devise Gem进行身份验证。如果有人想要在没有登录的情况下打开页面,那么它会重定向到sign_in页面,然后在登录后返回到用户尝试打开的页面。 我使用Redirect loop with 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”,则登录后不会返回此页面。
答案 0 :(得分:35)
寻求的最佳资源是官方回购/维基/问题,然后是SO。你找到的答案已经过时了。
只需在ApplicationController中添加以下内容 for versions 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
答案 1 :(得分:20)
您不需要所有这些代码。 Devise(作为最新版本)已经为您保存了位置。
请使用:
def after_sign_in_path_for(resource)
request.env['omniauth.origin'] || stored_location_for(resource) || root_url
end
这会将用户重定向到最新的omniauth.source,或者将stored_location重定向到最后一种情况,即根网址。
我以为我需要创建该方法,但Devise已经做到了。
答案 2 :(得分:4)
截至Devise 4,它对我无缝起作用:
设计会自动重定向登录并在您注册时注册 使用设计存储当前页面的位置
store_location_for(resource)
。要执行此操作,请编辑您的ApplicationController
inapp/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
答案 3 :(得分:4)
正如官方文档中所指出的,simpler solution只是将其添加到您的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!
中调用默认情况下在Devise中提供的before_action:
方法。这将调用store_location_for
可用out of the box in Devise,其余部分由application_controller.rb
中的上述代码处理,因此无需重写代码以保存请求网址。
答案 4 :(得分:2)
如果您的登录表单具有自己的页面,则此处的某些其他解决方案可能无效,而不是例如每页的标题中的登录表单。登录后,用户需要返回两个页面,而不仅仅是一个。
Devise在Redirecting back to the current page after sign in, sign out, update上有一个很好的操作方法,下面是代码。
在会话中存储原始URL是最佳选择。除了解决上述两个页面的问题之外,“许多浏览器不发送[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
答案 5 :(得分:0)
我有同样的疑问并发现了这一点,也尝试了
def after_sign_in_path_for(resource_or_scope)
session.fetch 'user_return_to', admin_root_path
end
答案 6 :(得分:0)
gem 'devise', '~> 4.4.0'
创建sessions_controller.rb:class SessionsController < Devise::SessionsController
添加以下内容(如果您的登录网址不是/ users,则修改正则表达式)
def before_login
session[:previous_url] = request.fullpath unless request.fullpath =~ /\/users/
end
def after_login
session[:previous_url] || root_path
end
请注意,如果您在/ users下有/ users / dashboard或其他位置,则此方法无效。可能希望通过正则表达式获得更具体的信息。
答案 7 :(得分: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