Rails: Warden/Devise - Как перехватить URL до входа в систему / неудачного доступа
Я пытаюсь выяснить, как перенаправить пользователя на страницу, с которой он вошел (или не смог войти), используя Warden/Devise. Я полагаю, что где-то есть переменная сеанса, которая либо доступна, либо может быть доступна.
Например, сценарий 1: неавторизованный пользователь переходит на защищенную страницу X; Перенаправлено на страницу входа; Пользователь входит в систему; Пользователь перенаправлен на защищенную страницу x
Сценарий 2: неавторизованный пользователь хочет предпринять защищенное действие на странице x; Пользователь нажимает на ссылку для входа; Пользователь входит в систему; Пользователь перенаправлен на страницу x, где теперь доступно действие
Любые указатели приветствуются.
Спасибо!
5 ответов
Существует вспомогательный метод devise 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
Ты можешь использовать request.referer
чтобы получить предыдущий URL
,
Если вы используете 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 для отслеживания защищенной страницы.
Вау, только что понял, что devise (3.5.2)
делает это само по себе за кулисами (вокруг Devise::SessionsController#new
действие), никаких дополнительных модификаций контроллера не требуется.
Если вам нужно явно 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
в приведенном выше примере). Смотрите источник для деталей.
Что касается фактического ответа, это будет что-то вроде этого:
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