Ruby on rails 使用Desive重置密码问题

Ruby on rails 使用Desive重置密码问题,ruby-on-rails,devise,passwords,forgot-password,Ruby On Rails,Devise,Passwords,Forgot Password,我在Rails应用程序中使用Desive,重置密码时遇到问题 当我尝试重置密码时,会收到一封电子邮件,其中包含重置密码的链接。使用新密码填写表单后,我在Chrome中出现错误“网页有重定向循环”,并且我在日志中出现以下错误: Started GET "/users/password/edit?reset_password_token=[FILTERED]" for 127.0.0.1 at 2013-12-19 14:22:05 -0500 Processing by Devise::Passw

我在Rails应用程序中使用Desive,重置密码时遇到问题

当我尝试重置密码时,会收到一封电子邮件,其中包含重置密码的链接。使用新密码填写表单后,我在Chrome中出现错误“网页有重定向循环”,并且我在日志中出现以下错误:

Started GET "/users/password/edit?reset_password_token=[FILTERED]" for 127.0.0.1 at 2013-12-19 14:22:05 -0500
Processing by Devise::PasswordsController#edit as HTML
  Parameters: {"reset_password_token"=>"[FILTERED]"}
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Redirected to http://localhost:3000/users/password/edit?reset_password_token=JatMT1fE-fQwsCWsEdy6
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 1.8ms (ActiveRecord: 0.4ms)
我似乎找不到任何关于如何解决这个问题的信息

user.rb

class User < ActiveRecord::Base
 ...
 devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :token_authenticatable, :confirmable, :lockable
 ...
end
Devise.setup do |config|
  ...
  config.reset_password_within = 6.hours
  ...
end
Build::Application.routes.draw do
  devise_for :users, :controllers => {:registrations => :registrations}

  devise_scope :user do
      post 'registrations' => 'registrations#create', :as => 'register'
      post 'sessions' => 'sessions#create', :as => 'login'
      delete 'sessions' => 'sessions#destroy', :as => 'logout'
    end

 resources :users do
     match 'users/:id' => 'users#username'
     get 'validate_username', on: :collection
     get 'validate_email', on: :collection
     get 'edit_profile', on: :member
     get :projects, on: :member
     get :favorites, on: :member
     get :collections, on: :member
     member do
      get :follow
      get :unfollow
      get :following
      get :followers
     end
  end
end
class RegistrationsController < Devise::RegistrationsController

    skip_before_filter :verify_authenticity_token,
                     :if => Proc.new { |c| c.request.format == 'application/json' }

    respond_to :json

    def create
        user = User.new(params[:user])
        Rails.logger.info(user.inspect)
        # comment out following line to re-enable confirmation
        # resource.skip_confirmation!

        if user.save
          sign_in user
          render :status => 200,
               :json => { :success => true,
                          :info => "Registered",
                          :data => { :user => user,
                                     :auth_token => current_user.authentication_token } }
        else
            redirect_to new_user_registration_path, notice: user.errors.full_messages[0]
            Rails.logger.info(user.errors.inspect)
          # render :status => :unprocessable_entity,
          #        :json => { :success => false,
          #                   :info => resource.errors,
          #                   :data => {} }
        end
    end

    def update
        @user = User.find(current_user.id)
        successfully_updated = if needs_password?(@user, params)
            @user.update_with_password(params[:user])
        else
            # remove the virtual current_password attribute 
            params[:user].delete(:current_password)
            @user.update_without_password(params[:user])
        end

        if successfully_updated
            if params[:update_email]
                set_flash_message :alert, :signed_up_but_unconfirmed
                redirect_to after_update_path_for(@user)
            else            
                set_flash_message :notice, :updated
                sign_in @user, :bypass => true
                redirect_to after_update_path_for(@user)
            end
        else
            redirect_to :back, alert: resource.errors.full_messages[0]
        end
    end

        private

    # check if we need password to update user data
    def needs_password?(user,params)
        !params[:profile]
    end

    protected

    def after_update_path_for(resource)
        user_path(resource)
    end

end
routes.rb

class User < ActiveRecord::Base
 ...
 devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :token_authenticatable, :confirmable, :lockable
 ...
end
Devise.setup do |config|
  ...
  config.reset_password_within = 6.hours
  ...
end
Build::Application.routes.draw do
  devise_for :users, :controllers => {:registrations => :registrations}

  devise_scope :user do
      post 'registrations' => 'registrations#create', :as => 'register'
      post 'sessions' => 'sessions#create', :as => 'login'
      delete 'sessions' => 'sessions#destroy', :as => 'logout'
    end

 resources :users do
     match 'users/:id' => 'users#username'
     get 'validate_username', on: :collection
     get 'validate_email', on: :collection
     get 'edit_profile', on: :member
     get :projects, on: :member
     get :favorites, on: :member
     get :collections, on: :member
     member do
      get :follow
      get :unfollow
      get :following
      get :followers
     end
  end
end
class RegistrationsController < Devise::RegistrationsController

    skip_before_filter :verify_authenticity_token,
                     :if => Proc.new { |c| c.request.format == 'application/json' }

    respond_to :json

    def create
        user = User.new(params[:user])
        Rails.logger.info(user.inspect)
        # comment out following line to re-enable confirmation
        # resource.skip_confirmation!

        if user.save
          sign_in user
          render :status => 200,
               :json => { :success => true,
                          :info => "Registered",
                          :data => { :user => user,
                                     :auth_token => current_user.authentication_token } }
        else
            redirect_to new_user_registration_path, notice: user.errors.full_messages[0]
            Rails.logger.info(user.errors.inspect)
          # render :status => :unprocessable_entity,
          #        :json => { :success => false,
          #                   :info => resource.errors,
          #                   :data => {} }
        end
    end

    def update
        @user = User.find(current_user.id)
        successfully_updated = if needs_password?(@user, params)
            @user.update_with_password(params[:user])
        else
            # remove the virtual current_password attribute 
            params[:user].delete(:current_password)
            @user.update_without_password(params[:user])
        end

        if successfully_updated
            if params[:update_email]
                set_flash_message :alert, :signed_up_but_unconfirmed
                redirect_to after_update_path_for(@user)
            else            
                set_flash_message :notice, :updated
                sign_in @user, :bypass => true
                redirect_to after_update_path_for(@user)
            end
        else
            redirect_to :back, alert: resource.errors.full_messages[0]
        end
    end

        private

    # check if we need password to update user data
    def needs_password?(user,params)
        !params[:profile]
    end

    protected

    def after_update_path_for(resource)
        user_path(resource)
    end

end
注册\u controller.rb

class User < ActiveRecord::Base
 ...
 devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :token_authenticatable, :confirmable, :lockable
 ...
end
Devise.setup do |config|
  ...
  config.reset_password_within = 6.hours
  ...
end
Build::Application.routes.draw do
  devise_for :users, :controllers => {:registrations => :registrations}

  devise_scope :user do
      post 'registrations' => 'registrations#create', :as => 'register'
      post 'sessions' => 'sessions#create', :as => 'login'
      delete 'sessions' => 'sessions#destroy', :as => 'logout'
    end

 resources :users do
     match 'users/:id' => 'users#username'
     get 'validate_username', on: :collection
     get 'validate_email', on: :collection
     get 'edit_profile', on: :member
     get :projects, on: :member
     get :favorites, on: :member
     get :collections, on: :member
     member do
      get :follow
      get :unfollow
      get :following
      get :followers
     end
  end
end
class RegistrationsController < Devise::RegistrationsController

    skip_before_filter :verify_authenticity_token,
                     :if => Proc.new { |c| c.request.format == 'application/json' }

    respond_to :json

    def create
        user = User.new(params[:user])
        Rails.logger.info(user.inspect)
        # comment out following line to re-enable confirmation
        # resource.skip_confirmation!

        if user.save
          sign_in user
          render :status => 200,
               :json => { :success => true,
                          :info => "Registered",
                          :data => { :user => user,
                                     :auth_token => current_user.authentication_token } }
        else
            redirect_to new_user_registration_path, notice: user.errors.full_messages[0]
            Rails.logger.info(user.errors.inspect)
          # render :status => :unprocessable_entity,
          #        :json => { :success => false,
          #                   :info => resource.errors,
          #                   :data => {} }
        end
    end

    def update
        @user = User.find(current_user.id)
        successfully_updated = if needs_password?(@user, params)
            @user.update_with_password(params[:user])
        else
            # remove the virtual current_password attribute 
            params[:user].delete(:current_password)
            @user.update_without_password(params[:user])
        end

        if successfully_updated
            if params[:update_email]
                set_flash_message :alert, :signed_up_but_unconfirmed
                redirect_to after_update_path_for(@user)
            else            
                set_flash_message :notice, :updated
                sign_in @user, :bypass => true
                redirect_to after_update_path_for(@user)
            end
        else
            redirect_to :back, alert: resource.errors.full_messages[0]
        end
    end

        private

    # check if we need password to update user data
    def needs_password?(user,params)
        !params[:profile]
    end

    protected

    def after_update_path_for(resource)
        user_path(resource)
    end

end
类注册控制器Proc.new{| c | c.request.format=='application/json'}
回复:json
def创建
user=user.new(参数[:user])
Rails.logger.info(user.inspect)
#注释掉以下行以重新启用确认
#resource.skip_确认!
如果user.save
登录用户
渲染:状态=>200,
:json=>{:success=>true,
:info=>“已注册”,
:data=>{:user=>user,
:auth\u token=>current\u user.authentication\u token}
其他的
重定向到新用户注册路径,注意:user.errors.full\u消息[0]
Rails.logger.info(user.errors.inspect)
#呈现:状态=>:无法处理的_实体,
#:json=>{:success=>false,
#:info=>resource.errors,
#:data=>{}
结束
结束
def更新
@user=user.find(当前用户id)
成功更新=是否需要密码?(@user,params)
@用户。使用密码更新用户(参数[:用户])
其他的
#删除虚拟当前密码属性
参数[:用户]。删除(:当前密码)
@user.update_而不使用_密码(参数[:user])
结束
如果成功更新
如果参数[:更新\u电子邮件]
设置\u闪存\u消息:警报,:已注册\u但\u未确认
重定向到(@user)的更新后路径
其他的
设置闪光信息:通知:更新
在@user中签名:旁路=>true
重定向到(@user)的更新后路径
结束
其他的
将\u重定向到:返回,警报:资源。错误。完整\u消息[0]
结束
结束
私有的
#检查是否需要密码来更新用户数据
def需要_密码?(用户,参数)
!参数[:配置文件]
结束
受保护的
更新后的def路径(资源)
用户路径(资源)
结束
结束

检查您在应用程序控制器中的“登录路径”后的重定向,如果是密码编辑请求,则将重定向添加到根url(而不是:back或request.env['HTTP\u REFERER'])。

我遇到了完全相同的问题,只是注意到重复重定向到密码重置url

我认为@Sergey Sokolov的答案是正确的,尽管我在路径中修改了我的后签名:

def after_sign_in_path_for(resource_or_scope)
   if request.referer.include? "reset_password"
     root_path
   else
     request.referer
   end
end
这样,在密码重置以外的情况下,用户将返回到他或她登录的页面。这避免了用户在电子邮件中遵循密码重置链接的问题


在排除故障时,我也做了一些非常愚蠢的事情,当我在测试时为另一个用户重置密码时,我仍然以另一个用户的身份登录。这会导致非常奇怪的行为。

控制器看起来如何?我添加了注册控制器。