2010-08-15 45 views
17

我想弄清楚如何將用戶重定向到他們使用Warden/Devise登錄(或登錄失敗)的頁面。我認爲有一個會話變量可用或可用。Rails:守望者/設計 - 如何捕獲登錄之前的網址/失敗的訪問

E.g. 情景1: 非授權用戶轉到受保護的頁面X; 重定向到登錄頁面; 用戶登錄; 用戶重定向到受保護頁面x

場景2: 非授權用戶希望在頁面x上採取受保護的操作; 用戶點擊登錄鏈接; 用戶登錄; 用戶重定向到第x頁,其中的動作現在可用

任何指針,讚賞。

謝謝!

回答

1

您可以使用request.referer來獲取以前的URL。

13

有一個名爲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 
+9

我不得不使用'會話[:user_return_to]'在此提到的SO回答:http://stackoverflow.com/a/5959018/337903 – Nick 2012-07-18 18:12:32

+1

會話[:user_return_to]使用此解決方案,因爲Nick表示 – 2012-12-02 18:21:11

+1

此答案的更簡潔版本(使用'user_return_to'而不是'user.return_to'):將會話session [:user_return_to] || root_path' – GMA 2014-08-20 08:50:10

1

如果您使用慘慘的授權,你可以做到這一點可以添加以下。如果沒有,您應該能夠將這些概念調整到您當前的授權系統中。

應用程序/控制器/ 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 %> 

而不是使用會話變量此解決方案的使用PARAMS的URL跟蹤受保護的頁面。

+0

任何不使用會話的理由?這是否適用於最新的設計版本? – justingordon 2012-11-18 08:00:13

+0

您可能需要添加如下內容:devise_scope:user do match'/ login'=>'users/sessions#new',如下所示:「login」 end否則rails會抱怨找不到login_path。截至2012年11月25日,這是最新的Devise。 – justingordon 2012-11-26 07:07:39

0

這裏是我能想到的最好的。與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 
1

哇,剛剛意識到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在上面的例子)。詳情請參閱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 
相關問題