Rails:Warden / Devise – 如何在登录/访问失败之前捕获URL
我试图弄清楚如何使用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
方法需要返回一个字符串,然后设计会在登录后自动使用该路径重定向用户。
在我的应用程序控制器中,如果未设置会话变量,我已将以下内容重定向到主页:
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
应用程序/视图/设计/会话/ new.html.erb
<% if params[:next] %> <%= f.hidden_field :next, :value => params[:next] %> <% end %>
此解决方案不使用会话变量,而是使用URL中的params来跟踪受保护的页面。
哇,刚刚意识到devise (3.5.2)
在幕后(围绕Devise::SessionsController#new
action)完成了这一切,不需要额外的控制器修改。
如果您需要明确store
/ get
以前的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
)。 有关详细信息,请参阅source 。
至于实际答案,它将是这样的:
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
您可以使用request.referer
获取以前的URL
。
这是我能想到的最好的。 与facebook身份validation完美配合。 通过为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