2016-07-02 1 views
1

비밀번호 재설정 링크가 이메일을 통해 전송되면 작동하지 않는 것 같습니다.Michael Hartl Chap 12 비밀번호 재설정이 홈페이지로 리디렉션 됨

필터 체인뿐만 정지 : 때문에이를 클릭하면 홈페이지로 리디렉션 결과 valid_user 렌더링하거나 여기

리디렉션은 valid_user

# Confirms a valid user. 
    def valid_user 
     unless (@user && @user.activated? && 
       @user.authenticated?(:reset, params[:id])) 
     redirect_to root_url 
     end 
    end 

PasswordsResetsController

class PasswordResetsController < ApplicationController 
    before_action :get_user,   only: [:edit, :update] 
    before_action :valid_user,  only: [:edit, :update] 
    before_action :check_expiration, only: [:edit, :update] # Case (1) 

    def new 
    end 

    def create 
    @user = User.find_by(email: params[:password_reset][:email].downcase) 
    if @user 
     @user.create_reset_digest 
     @user.send_password_reset_email 
     flash[:info] = "Email sent with password reset instructions" 
     redirect_to root_url 
    else 
     flash.now[:danger] = "Email address not found" 
     render 'new' 
    end 
    end 

    def edit 
    end 

    def update 
    if params[:user][:password].empty?     # Case (3) 
     @user.errors.add(:password, "can't be empty") 
     render 'edit' 
    elsif @user.update_attributes(user_params)   # Case (4) 
     log_in @user 
     flash[:success] = "Password has been reset." 
     redirect_to @user 
    else 
     render 'edit'          # Case (2) 
    end 
    end 

    private 

    def user_params 
     params.require(:user).permit(:password, :password_confirmation) 
    end 

    # Before filters 

    def get_user 
     @user = User.find_by(email: params[:email]) 
    end 

    # Confirms a valid user. 
    def valid_user 
     unless (@user && @user.activated? && 
       @user.authenticated?(:reset, params[:id])) 
     redirect_to root_url 
     end 
    end 

    # Checks expiration of reset token. 
    def check_expiration 
     if @user.password_reset_expired? 
     flash[:danger] = "Password reset has expired." 
     redirect_to new_password_reset_url 
     end 
    end 
end 

User.rb

class User < ActiveRecord::Base 
    attr_accessor :remember_token, :activation_token, :reset_token 
    before_save :downcase_email 
    before_create :create_activation_digest 
    validates :name, presence: true, length: { maximum: 50 } 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, length: { maximum: 255 }, 
        format: { with: VALID_EMAIL_REGEX }, 
        uniqueness: { case_sensitive: false } 
    validates :username, presence: true, length: { maximum: 50 } 
    has_secure_password 
    validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 

    # Returns the hash digest of the given string. 
    def User.digest(string) 
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 
                BCrypt::Engine.cost 
    BCrypt::Password.create(string, cost: cost) 
    end 

    # Returns a random token. 
    def User.new_token 
    SecureRandom.urlsafe_base64 
    end 

    # Remembers a user in the database for use in persistent sessions. 
    def remember 
    self.remember_token = User.new_token 
    update_attribute(:remember_digest, User.digest(remember_token)) 
    end 

    # Returns true if the given token matches the digest. 
    def authenticated?(attribute, token) 
    digest = send("#{attribute}_digest") 
    return false if digest.nil? 
    BCrypt::Password.new(digest).is_password?(token) 
    end 

    # Forgets a user. 
    def forget 
    update_attribute(:remember_digest, nil) 
    end 

    # Activates an account. 
    def activate 
    update_attribute(:activated, true) 
    update_attribute(:activated_at, Time.zone.now) 
    end 

    # Sends activation email. 
    def send_activation_email 
    UserMailer.account_activation(self).deliver_now 
    end 

    # Sets the password reset attributes. 
    def create_reset_digest 
    self.reset_token = User.new_token 
    update_attribute(:reset_digest, User.digest(reset_token)) 
    update_attribute(:reset_sent_at, Time.zone.now) 
    end 

    # Sends password reset email. 
    def send_password_reset_email 
    UserMailer.password_reset(self).deliver_now 
    end 

    # Returns true if a password reset has expired. 
    def password_reset_expired? 
    reset_sent_at < 2.hours.ago 
    end 

    private 

    # Converts email to all lower-case. 
    def downcase_email 
    self.email = email.downcase 
    end 

    # Creates and assigns the activation token and digest. 
    def create_activation_digest 
    self.activation_token = User.new_token 
    self.activation_digest = User.digest(activation_token) 
    end 

end 

왜 이렇게하는지 모르겠습니다. 인증을 제거하면? valid_user 메소드에있는 코드의 일부만 삭제하면 여전히 홈페이지로 리디렉션됩니다.

답변

2

문제는 내가 만든 사용자를 사용하여이 테스트를 수행했으며 사용자를 만든 방식 때문에 "활성화"방법을 사용하지 않았다는 것입니다. 웹 사이트에서 가입 프로세스를 진행하는 사용자와 테스트를 거쳤습니다.

+0

문제를 해결할 수있어서 기쁩니다. 직접 답변 수락을 고려하십시오. http://meta.stackexchange.com/a/5235/249307 – SoAwesomeMan

1

application_controller.rbbefore_filter :valid_user이 있다고 가정합니다. 그렇다면 valid_user에 조건을 추가하여 인증 및 활성화 확인을 방지하십시오. 당신이 당신의 password_resets_controller.rbbefore_filter :valid_user이있는 경우 사용 사례가 포함되어 있기 때문에, 당신은 단지 그것을 제거 할 수

def valid_user 
    unless controller_name == "password_resets" 
    unless (@user && @user.activated? && 
      @user.authenticated?(:reset, params[:id])) 
     redirect_to root_url 
    end 
    end 
end 

: 사용자가 인증되지 않습니다하려고 예를 들어, 당신은 당신의 필요에 따라 다음과 같은 방법을 조정할 수 비밀번호를 재설정하십시오.

+1

좋은 해결 방법 인 것 같습니다. 나는 그걸로 뭔가를 놓치고있는 것 같은 기분이야. 그게 보안 허점을 일으키지 않을까요? 재설정 토큰이 다이제스트와 일치하므로 인증되지 않아야합니까? – Doughtz

+0

좋은 질문입니다. 나는 Hartl로부터 아무 것도 읽지 않았고 토큰이 신분증이 아닌 것을 고려하지 않았다. 재설정 토큰에 JWT와 같은 것을 사용하면 현명합니다. – SoAwesomeMan

관련 문제