使用 rails 4 认证的根路由进行设计无法正常工作

Posted

技术标签:

【中文标题】使用 rails 4 认证的根路由进行设计无法正常工作【英文标题】:Devise with rails 4 authenticated root route not working 【发布时间】:2013-09-30 15:06:05 【问题描述】:

我想要做什么

如果用户没有登录,我想将他们发送到registrations#new 页面。

在您输入登录信息并单击提交后,我希望您被发送到注册#show 页面。

发生了什么

当您未登录时,它会将您转到registrations#new 页面(目前为止正确)。但是当您提交登录表单时,它会通过重定向循环发送错误。服务器的输出就是这个块一遍又一遍地重复:

Started GET "/" for 127.0.0.1 at 2013-09-25 02:31:59 -0400
Processing by RegistrationsController#new as html
  User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 8 ORDER BY "users"."id" ASC LIMIT 1
Redirected to http://lvh.me:3000/
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 2ms (ActiveRecord: 0.7ms)

我似乎无法弄清楚。它确实让您登录,正如我所看到的,通过手动导航到不同的页面,但 authenticated 根路径无法正常工作。我在我的路线文件中尝试了几种不同的组合,但似乎无法得到它。我使用的代码基于this thread

我的代码

在我的应用程序控制器中,我有 before_filter :authenticate_user!

我的路线文件:

devise_for :users, :controllers => 
  :registrations => "registrations"


devise_scope :user do
  root to: "registrations#new"
end

authenticated :user do
  root to: "registrations#show", :as => "profile"
end

unauthenticated do
  root to: "registrations#new", :as => "unauthenticated"
end

【问题讨论】:

【参考方案1】:

首先要自定义Devise::RegistrationsController(可以添加文件app/controllers/registrations_controller.rb

并在设计registrations_controller.rb 上查看prepend_before_filter

prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]

show 操作添加到prepend_before_filter :authenticate_scope!

registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
  prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
  prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy, :show]

  # GET /resource/sign_up
  def new
    super
  end

  # POST /resource
  def create
    super
  end

  # GET /resource/edit
  def edit
    super
  end

  def update
    super
  end

  # DELETE /resource
  def destroy
    super
  end

  def show
  end


  protected

  def after_sign_up_path_for(resource)
    after_sign_in_path_for(resource)
  end

end

还将devise registration(编辑和新模板)的视图复制到/app/views/registrations/,您可以在/app/views/registrations/ 文件夹中为个人资料页面创建一个文件show.html.erb

设计路线如下:

devise_for :users, :skip => [:registrations]

devise_for :users, :controllers => 
  :registrations => "registrations"


authenticated :user do
  devise_scope :user do
    root to: "registrations#show", :as => "profile"
  end
end

unauthenticated do
  devise_scope :user do
    root to: "registrations#new", :as => "unauthenticated"
  end
end

最后,您在文件 application_controller.rb

中设置 after_sign_in_path_for(resource)after_sign_out_path_for(resource_or_scope) 中的“路径”
class ApplicationController < ActionController::Base
  protect_from_forgery

  private

   def after_sign_in_path_for(resource)
     # After you enter login info and click submit, I want you to be sent to the registrations#show page
     profile_path
   end
   def after_sign_out_path_for(resource_or_scope)
     new_user_session_path
   end
end

注意:我已经尝试过这个(制作示例应用程序),它可以工作。登录时查看日志here,注销时查看here

【讨论】:

酷我明天试试这个。您是否尝试过使用 rails 4 应用程序? 干得好。我所做的只是将我的路线文件修改为像你的一样!经过身份验证和/或未经身份验证的 devise_scope。然后,我在经过身份验证的 devise_scope 块中添加了其余的登录路由 非常感谢。这拯救了我的一天。使用 prepend_before_filter :require_no_authentication,仅:[:edit, :update] prepend_before_filter :authenticate_scope!,除了:[:edit, :update]【参考方案2】:

默认重定向到registration#new,所以你需要做的就是这个(在你的路由文件中):

devise_for :users, :controllers => 
  :registrations => "registrations"


devise_scope :user do
  root to: "registrations#show" # This is the root path of the user when you are logged in
end

unauthenticated do
  root to: "registrations#new", :as => "unauthenticated"
end

# I dont't think this part is neccesary... Try if it works without
authenticated :user do
  root to: "registrations#show", :as => "profile"
end

【讨论】:

但这不使用我看到提到的authenticatedunauthenticated方法 抱歉忘记了unathenticated,但是当你有devise_scoperoot 时,我认为authenticated 是不必要的。但是当我有时间时,我会尝试进行更多测试:)。 这看起来和我的问题一模一样吗? 不,您在 devise_scope 块中有 root to: "registrations#new",这正是您的问题的主要原因。【参考方案3】:

不要使用路由来做属于控制器的工作。

要在注册后将用户重定向到特定页面,请使用 Devise 内置的 after_sign_up_path_for 并覆盖它。

class ApplicationController
  def after_sign_up_path_for(resource)
    faked_user_profile_path(resource)
  end
end

对于路线,除了devise_for 部分,我不是很了解所有路线。但是对于重定向功能,这种覆盖应该足够了。

【讨论】:

我会试试这个,但根据设计文档,这是这样做的方法...... TMP,我没有阅读完整的 Devise wiki 并且不知道那部分,所以我最后的陈述可能不准确,我将删除它。但是,要实现您要求的功能,方法覆盖应该足够简单。 由于某种原因,我仍然收到重定向循环,我感觉 after_sign_up_path_for 无法正常工作,并且仍在将其发送回 root 没关系,你完全正确,我只需要定义after_sign_in_path_for,因为注册和两者都需要去某个地方。我将推迟接受这一点,因为我仍然想知道使用authenticated :user do 的更多设计方法 更新:第二好的答案实际上是signed_in_root_path,但仍然想authenticated 根答案

以上是关于使用 rails 4 认证的根路由进行设计无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

TOMCAT配置HTTPS双向认证,为啥始终无法访问

markdown 使用Bcrypt在Rail 4中进行简单认证

markdown 使用Bcrypt在Rail 4中进行简单认证

Rails 4 - best_in_place:无法处理的实体

Rails,设计认证,CSRF 问题

Rails 4 + 设计:密码重置总是在生产服务器上给出“令牌无效”错误,但在本地工作正常。