繁体   English   中英

使用Rails重定向登录后无法理解Devise

[英]Failing to understand Devise after sign in redirect with Rails

我是一个Rails / devise新手,我已经做了几个月的搜索,但没有找到解决方案。

我想做的事情似乎很简单:使用Rails和Devise gem(v 3.2.3)成功登录后,将用户重定向到上一页,但是我所有的登录重定向都转到根路径。 这很烦人,因为如果我向某人发送指向他们必须在其中进行身份验证的特定页面的链接,它将再次将他们重定向到主页。

我知道其他有关SO的问题也会提出这个问题,但我想我是在问有关Devise中代码的更高层次的问题。

所以我的总体问题是:我对问题和解决方案的理解正确吗? 为了解决,我需要:

  • 存储用户会话中的上一页
  • 在after_sign_in_path函数中重定向到该位置

我在第177行的Devise lib / devise / controllers / helpers.rb中查看一些代码注释:

# The default url to be used after signing in. This is used by all Devise
  # controllers and you can overwrite it in your ApplicationController to
  # provide a custom hook for a custom resource.
  #
  # By default, it first tries to find a valid resource_return_to key in the
  # session, then it fallbacks to resource_root_path, otherwise it uses the
  # root path. For a user scope, you can define the default url in
  # the following way:

然后在该文件的第204行:

def after_sign_in_path_for(resource_or_scope)
  stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
end

这使我在store_location.rb的stored_location_for方法:

def stored_location_for(resource_or_scope)
  session_key = stored_location_key_for(resource_or_scope)
  if is_navigational_format?
    session.delete(session_key)
  else
    session[session_key]
  end
end

因此,当新用户登录时,将在session#create中调用代码:

# POST /resource/sign_in
def create
  self.resource = warden.authenticate!(auth_options)
  set_flash_message(:notice, :signed_in) if is_flashing_format?
  sign_in(resource_name, resource)
  yield resource if block_given?
  respond_with resource, location: after_sign_in_path_for(resource)
end

然后调用我上面粘贴的after_sign_in_path_for(resource) 我的问题是:这是否是我能够将某人重定向到上一页而不是根路径所需的一切? 是否需要补充一些遗漏? 如何测试after_sign_in_path_for(resource)不为零? 其他人有经验吗?

仅供参考,这里是我的路线文件:

Rails.application.routes.draw do
  get 'orders/index'
  resources "orders", :controller => :my_orders, :as => :orders
  get 'faq/index'
  resources "faq", :controller => :faq, :as => :faq
  get 'guidelines/index'
  resources "guidelines", :controller => :guidelines, :as => :guidelines
  get 'terms_of_use/index'
  resources "terms-of-use", :controller => :terms_of_use, :as => :terms_of_use
  get 'privacy_policy/index'
  resources "privacy-policy", :controller => :privacy_policy, :as => :privacy_policy

  # This line mounts Spree's routes at the root of your application.
  # This means, any requests to URLs such as /products, will go to Spree::ProductsController.
  # If you would like to change where this engine is mounted, simply change the :at option to something different.
  #
  # We ask that you don't use the :as option here, as Spree relies on it being the default of "spree"
  mount Spree::Core::Engine, :at => '/store'

# Need to adjust this for FB authentication
  devise_for :users, controllers: { registrations: 'users/registrations', passwords: 'users/passwords' }

  devise_scope :user do
    get 'register', to: 'devise/registrations#new', as: :register
    get 'signin', to: 'devise/sessions#new', as: :signin
    get 'logout', to: 'devise/sessions#destroy', as: :logout
    get 'edit', to: 'devise/registrations#edit', as: :edit
    put "update" => 'devise/registrations#update', as: :updateprofile
  end

  get 'welcome/index'

  get '/sell' => 'sell#index'

  get '/:id', to: 'profiles#show', as: :profile

  root 'welcome#index'

  # for setting up the stripe webhook
  post '/hooks/stripe' => 'hooks#stripe'


end

如果有用的话,我会很高兴地透露更多的代码。

先感谢您,

  • 布兰登

编辑做了更多的挖掘以缩小范围。 我注释掉了store_location.rb中的许多代码,以查看会话密钥。 注释掉if / else语句,因为它是一种导航格式,显然(这意味着什么?):

  def stored_location_for(resource_or_scope)
    session_key = stored_location_key_for(resource_or_scope)
    puts "session_key = #{session_key}"
    puts "session = #{session}"
    puts "session[session_key] = #{session[session_key]}"
    # if is_navigational_format?
    #   puts "is navigational"
    #   session.delete(session_key)
    # else
    #   puts "is not navigational"
    puts "session[session_key] = #{session[session_key]}"
    session[session_key]
    # end
  end

并且我在此方法中添加了一些与session_key绑定的put语句。

  def stored_location_key_for(resource_or_scope)
    scope = Devise::Mapping.find_scope!(resource_or_scope)
    "#{scope}_return_to"
  end

这是命令行中的输出:

Started POST "/users/sign_in" for 127.0.0.1 at 2015-05-03 22:34:31 -0500
Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"/Xjy/neoPX2nGqpz+FtACjtTx4nnkhiRuVln44Zi4qI=", "user"=>{"email"=>"brandon.a.hay@gmail.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}
  User Load (0.3ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = 'brandon.a.hay@gmail.com'  ORDER BY "users"."id" ASC LIMIT 1
   (0.1ms)  begin transaction
  SQL (0.3ms)  UPDATE "users" SET "current_sign_in_at" = ?, "last_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 7  [["current_sign_in_at", "2015-05-04 03:34:31.179646"], ["last_sign_in_at", "2015-05-04 03:32:08.608830"], ["sign_in_count", 65], ["updated_at", "2015-05-04 03:34:31.181312"]]
  Spree::Role Load (0.1ms)  SELECT  "spree_roles".* FROM "spree_roles"  WHERE "spree_roles"."name" = 'admin' LIMIT 1
  SQL (0.1ms)  INSERT INTO "spree_roles_users" ("role_id", "user_id") VALUES (?, ?)  [["role_id", 1], ["user_id", 7]]
   (1.5ms)  commit transaction
session_key = user_return_to
session = #<ActionDispatch::Request::Session:0x007fc7c4af34b0>
session[session_key] =
stored location =
session_key = user_return_to
session = #<ActionDispatch::Request::Session:0x007fc7c4af34b0>
session[session_key] =
Redirected to http://localhost:3000/

因此,stored_location_key_for返回用户类并将其绑定到作用域。 session_key返回“ user_return_to”,session返回一个动作分配请求会话,session [session_key]为nil。 有人可以帮助我理解这一点吗?

这篇文章的答案解决了我的问题: 使用omniauth重定向回当前页面并设计

我必须在应用程序控制器中添加商店位置回调:

#application_controller.rb
before_filter :store_current_location, :unless => :devise_controller?

def store_current_location
  store_location_for(:user, request.url)
end

您需要像这样重定向控制器中的路由

class HomeController < ApplicationController
    def index
        if user_signed_in?
            redirect_to blogs_index_path
        end
    end
end

转到终端并输入耙路径,找到所需的路径,然后将其重定向到那里。 希望这可以帮助!

似乎尝试存储的位置永远不会存储在错误的位置。 看看这段代码https://github.com/plataformatec/devise/blob/v3.2.3/lib/devise/failure_app.rb

身份验证失败时,总是会调用失败应用程序。 您可以在第57行看到它存储了已访问的uri。 您可以尝试在此位置进行调试。

我可以想到几个为什么这不起作用的原因:

  • 您正在使用不存储位置的其他故障应用程序
  • 会话密钥在失败应用中不正确
  • 有一些代码可以清除存储的位置

如果找不到导致问题的原因,则可以尝试将代码从设计失败应用程序复制到应用程序控制器。 使用prepend_before_filter将位置存储在任何其他before_filters之前。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM