我已经为我的控制器创建了自己的身份验证功能,不仅可以验证用户是否已登录(如果他们是管理员等)。我发现的问题是,如果此人未登录并尝试访问需要身份验证的页面,则会成功将其重定向到登录页面,但在登录后,他们不会被发送回他们所在的页面试图访问。
我已将以下内容添加到ApplicationController
:
before_filter :store_location
def store_location
p "storing location"
# store last url - this is needed for post-login redirect to whatever the user last visited.
return unless request.get?
if (request.path != "/users/sign_in" &&
request.path != "/users/sign_up" &&
request.path != "/users/password/new" &&
request.path != "/users/password/edit" &&
request.path != "/users/confirmation" &&
request.path != "/users/sign_out" &&
!request.xhr?) # don't store ajax calls
session[:previous_url] = request.fullpath
end
end
def after_sign_in_path_for(resource)
session["user_return_to"] || root_path
end
def new_authorize_employee
if current_user.nil?
redirect_to new_user_session_path, notice: "You must be signed in to access this page."
else
unless current_user.is_employee?
redirect_to root_path, notice: "You do not have permissions to access this page."
end
end
end
并且在用户尝试访问的控制器中:
class EmployeesController < ApplicationController
before_action :new_authorize_employee
...
end
但登录后用户仍会被重定向到root_url
。如何更改身份验证方法以允许重定向到用户尝试访问的最后一页?
答案 0 :(得分:0)
Devise有一个built in mechanism用于存储位置。
class ApplicationController < ActionController::Base
before_action :store_location!,
unless: -> { devise_controller? || request.xhr? },
if: -> { request.get? && is_navigational_format? }
before_action :authenticate_user!,
unless: :devise_controller? # prevents a circular redirect
private
def store_location!
# from Devise::Controllers::StoreLocation
# :user is the scope
store_location_for(:user, request.fullpath)
end
end
需要在:store_location!
之前放置:authenticate_user!
回调,因为:authenticate_user!
将暂停过滤器链并重定向,然后才能存储该位置。
使用if:
和unless:
选项可以将条件应用于控制器回调。请注意,这与if
和unless
ruby关键字不同。
devise_controller?
和is_navigational_format?
是Devise助手。 devise_controller?
应该用于跳过任何与Devise相关的控制器中的回调,而不是将特定路径列入黑名单。默认的可导航格式为['*/*', :html]
。
无需覆盖after_sign_in_path_for
,因为它已使用存储的位置:
def after_sign_in_path_for(resource_or_scope)
stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
end