我试图弄清楚如何使用 Warden/Devise 将用户重定向到他们登录(或登录失败)的页面。我认为某处有一个会话变量可用或可以使用。
例如场景1:非授权用户访问受保护页面X;重定向到登录页面;用户登录;用户重定向到受保护的页面 x
场景 2:非授权用户想要在页面 x 上执行受保护的操作;用户点击登录链接;用户登录;用户重定向到页面 x,该操作现在可用
任何指针表示赞赏。
谢谢!
我试图弄清楚如何使用 Warden/Devise 将用户重定向到他们登录(或登录失败)的页面。我认为某处有一个会话变量可用或可以使用。
例如场景1:非授权用户访问受保护页面X;重定向到登录页面;用户登录;用户重定向到受保护的页面 x
场景 2:非授权用户想要在页面 x 上执行受保护的操作;用户点击登录链接;用户登录;用户重定向到页面 x,该操作现在可用
任何指针表示赞赏。
谢谢!
有一个名为after_sign_in_path_for(resource)( http://rdoc.info/github/plataformatec/devise/master/Devise/Controllers/Helpers ) 的设计助手方法,以及一个名为的会话变量session[:"user.return_to"],用于存储最后一个 url。该after_sign_in_path_for方法需要返回一个字符串,然后devise在登录后自动使用该路径重定向用户。
在我的应用程序控制器中,如果未设置会话变量,我将以下内容重定向到主页:
def after_sign_in_path_for(resource)
(session[:"user.return_to"].nil?) ? "/" : session[:"user.return_to"].to_s
end
如果您使用 CanCan 进行授权,您可以通过添加以下内容来完成此操作。如果没有,您应该能够将这些概念调整到您当前的授权系统中。
应用程序/控制器/application_controller.rb
rescue_from CanCan::AccessDenied do |exception|
flash[:error] = exception.message
if user_signed_in?
redirect_to root_url
else
# Adds the protected page to the login url but only if the user is not logged in
redirect_to login_path(:next => request.path)
end
end
def after_sign_in_path_for(resource_or_scope)
# if a protected page found, then override the devise after login path
params[:user]["next"] || super
end
app/views/devise/sessions/new.html.erb
<% if params[:next] %>
<%= f.hidden_field :next, :value => params[:next] %>
<% end %>
该解决方案不使用会话变量,而是使用 URL 中的参数来跟踪受保护的页面。
您可以使用request.referer获取以前的URL.
哇,刚刚意识到devise (3.5.2)这一切都是在幕后(围绕Devise::SessionsController#new动作)自己完成的,不需要额外的控制器修改。
如果您需要明确store/ getprevious location,请参阅我之前的回答:
目前(2015 年秋季)有一种更性感的方式来做到这一点:
Devise::Controllers::StoreLocation#store_location_for:
# Stores the provided location to redirect the user after signing in.
# Useful in combination with the `stored_location_for` helper.
store_location_for :user, dashboard_path
redirect_to user_omniauth_authorize_path :facebook
Devise::Controllers::StoreLocation#stored_location_for:
# Returns and delete (if it's navigational format) the url stored in the session for
# the given scope. Useful for giving redirect backs after sign up:
redirect_to stored_location_for(:user) || root_path
这些方法在读取后处理相关的session键和值删除,您只需要提供您的:resource键(:user在上面的示例中)和存储路径(dashboard_path在上面的示例中)。有关详细信息,请参阅来源。
至于实际答案,它会是这样的:
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied, with: :access_denied
# ...
private
def access_denied(exception)
store_location_for :user, request.path
redirect_to user_signed_in? ? root_path : new_user_session_path, alert: exception.message
end
def after_sign_in_path_for(resource)
stored_location_for(:user) || root_path
end
end
这是我能想到的最好的。也可以与 facebook 身份验证完美配合。通过在会话变量的 url 前添加更多限制,您可以删除越来越多不希望用户返回的路径(例如回调、启动页面、登录页面等)
#ApplicationsController
after_filter :store_location
def store_location
session[:previous_urls] ||= []
# store unique urls only
session[:previous_urls].prepend request.fullpath if session[:previous_urls].first != request.fullpath && request.fullpath != "/user" && request.fullpath != "/user/login" && request.fullpath != "/" && request.fullpath != "/user/logout" && request.fullpath != "/user/join" && request.fullpath != "/user/auth/facebook/callback"
# For Rails < 3.2
# session[:previous_urls].unshift request.fullpath if session[:previous_urls].first != request.fullpath
session[:previous_urls].pop if session[:previous_urls].count > 3
end
def after_sign_in_path_for(resource)
@url = session[:previous_urls].reverse.first
if @url != nil
"http://www.google.com" + @url
else
root_path
end
end