Ошибка аутентификации при изменении столбца в таблице Users - PullRequest
0 голосов
/ 05 мая 2011

Я очень плохо знаком с рельсами и пытаюсь решить следующую проблему аутентификации:

Пользователь комментирует или предоставляет «отпущение грехов» (аналогично комментарию) и получает за это несколько монет. Монеты - это виртуальная валюта в моем приложении, а также столбец в таблице пользователей.

Благодаря вашей доброй помощи я уже смог обновить стоимость монет после написания комментария или предоставления отпущения грехов. Тем не менее, когда я пишу комментарий и выхожу после этого, мое имя пользователя или пароль меняются (?) ... Я больше не могу войти с этой учетной записью.

Вот так выглядит моя модель пользователя:

require 'digest'
class User < ActiveRecord::Base

attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation, :twitter_url, :homepage_url, :coins

has_many :comments, :dependent => :destroy
has_many :absolutions, :dependent => :destroy

has_many :ratings
has_many :rated_sins, :through => :ratings, :source => :sins

email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
homepage_regex = /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix

validates :name,  :presence => true,
                  :length => { :maximum => 50 }
validates :email, :presence => true,
                  :format => { :with => email_regex },
                  :uniqueness => { :case_sensitive => false }
validates :twitter_url, :format => { :with => homepage_regex }
validates :homepage_url, :format => { :with => homepage_regex }
validates :password, :presence => true,
                     :confirmation => true,
                     :length => { :within => 6..40 }

before_save :encrypt_password

def has_password?(submitted_password)
  encrypted_password == encrypt(submitted_password)
end

def self.authenticate(email, submitted_password)
  user = find_by_email(email)
  return nil  if user.nil?
  return user if user.has_password?(submitted_password)
end

class << self
  def authenticate(email, submitted_password)
    user = find_by_email(email)
    (user && user.has_password?(submitted_password)) ? user : nil
  end

  def authenticate_with_salt(id, cookie_salt)
    user = find_by_id(id)
    (user && user.salt == cookie_salt) ? user : nil
  end
end

private

  def encrypt_password
    self.salt = make_salt if new_record?
    self.encrypted_password = encrypt(password)
  end

  def encrypt(string)
    secure_hash("#{salt}--#{string}")
  end

  def make_salt
    secure_hash("#{Time.now.utc}--#{password}")
  end

  def secure_hash(string)
    Digest::SHA2.hexdigest(string)
  end
end

А это мой контроллер комментариев:

class CommentsController < ApplicationController

  before_filter :authenticate, :only => [:create, :destroy]

  def new
    @comment = Comment.new
  end

  def create
    @sin = Sin.find(params[:sin_id])
    @comment = current_user.comments.build(params[:comment])
    @comment.sin_id = @sin.id
    if @comment.save
      flash[:success] = "Comment created! Earned 20 coins."
      coins_new = current_user.coins.to_i + 20
      current_user.update_attribute(:coins, coins_new)
      redirect_to sin_path(@sin)
    else
      flash[:error] = "Comment should have 1 - 1000 chars."
      redirect_to sin_path(@sin)
    end
  end

  def destroy
  end



  private 

    def authenticate
      deny_access unless signed_in?
    end

end

Я предполагаю, что это как-то связано с методом before_save encrypt_password, но это только предположение. Я очень ценю вашу помощь и предложения!

Edit: Становится теплее ... Это как-то связано со следующей строкой в ​​контроллере комментариев:

current_user.update_attribute(:coins, coins_new)

Когда он обновляет столбец: coins, что-то идет не так. Если вам нужна дополнительная информация, просто оставьте комментарий. Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 06 мая 2011

Ваша проблема в том, что вы шифруете уже зашифрованный пароль в своем методе "encrypt_password".

Итак, когда пользователь new_record?, вы берете пароль (скажем, это "кошка""), хэширование и сохранение в базе данных.

Итак, что хранится, это криптографический хеш" cat ", который мы будем называть" dog "

Затем,в следующий раз, когда вы сохраняете запись пользователя, вы берете хешированный пароль («собака») в строке # 2 вашего метода «encrypt_password» и снова хешируете его , что мы скажемгенерирует "kangaroo".

При следующем входе в систему ваше приложение хэширует пароль, который вы вводите в форму входа "cat", хэшируете его в "dog" и сравниваете его с хешированной версией в базе данных., "кенгуру".О, но "собака" не соответствует "кенгуру", поэтому вход в систему не удается.

Итак, измените:

def encrypt_password
  self.salt = make_salt if new_record?
  self.encrypted_password = encrypt(password)
end

На любой:

def encrypt_password
  self.salt = make_salt if new_record?
  self.password = decrypt(password) # decrypt it first to the plain text
  self.encrypted_password = encrypt(password) # then re-encrypt the plain text with the salt
end

или:

def encrypt_password
  self.salt = make_salt if new_record?
  if (password_has_changed?) # somehow you'll have to figure this out
    self.encrypted_password = encrypt(password)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...