Парольная аутентификация с использованием BCrypt

Я пытаюсь создать очень простую страницу входа с аутентификацией по имени пользователя и паролю с помощью BCrypt.

Есть две функции: первая - это создание имени пользователя и пароля, а вторая - аутентификация с использованием страницы входа. (создайте нового пользователя, войдите под этим пользователем)

Ниже приведен код модели контроллера и пользователя для создания имени пользователя и пароля. Модель просмотра не включена, но включает простую форму, в которой пользователю предлагается создать имя пользователя, пароль и подтвердить пароль.

Контроллер:

get '/new_user' do 
    erb :new_user
end 

post '/new_user' do
    if @password == @password_confirm
        new_user = User.new(username: params[:username])
        new_user.password = params[:password]
        new_user.insert_user
        redirect '/index'
    else
        redirect '/new_user'
    end 
end 

Модель:

def initialize(params = {})
    @username = params.fetch(:username, "test")
    @password = params.fetch(:password, "test")
end 

def password=(new_password)
    @password = BCrypt::Password.create(new_password)
    @db_password = BCrypt::Password.new(@password)
end 

def insert_user
    db = SQLite3::Database.open("helper_database")
    db_results_as_hash = true
    db.execute("INSERT INTO users (username, password) VALUES (?,?)", [@username, @db_password])
end 

В приведенном выше примере создается новый экземпляр для передачи имени пользователя и пароля. Если пароль и подтверждение пароля совпадают, метод пароля создаст зашифрованный пароль, а метод вставки вставит имя пользователя и зашифрованный пароль в базу данных с помощью простой команды SQL.

После того, как имя пользователя и зашифрованный пароль были вставлены в базу данных. Я хочу использовать страницу входа для проверки. Я создаю новый экземпляр User, передавая параметры имени пользователя и пароля методу аутентификации, показанному ниже. Метод будет искать пароль, соответствующий имени пользователя params, и сравнивать пароль params с зашифрованным паролем.

Ниже представлены контроллер и модель пользователя для входа в систему.

Контроллер:

get '/login' do 
 erb :login
end 

post '/login' do 
    @user = User.new(username: params[:username], password: params[:password])
    if @user.authenticate()
        redirect '/index'
    else 
        erb :login
    end 
end 

Модель:

    def authenticate
        db = SQLite3::Database.open("helper_database")
        db.results_as_hash = true
        password = db.execute("SELECT password FROM users WHERE username = '#{@username}'")
        password = password[0]["password"]
        password = BCrypt::Password.new(password)
        @password == password
  end 

Выше я пытаюсь получить зашифрованный пароль (строковый формат) из SQL, преобразовать его в объект Bcrypt и проверить пароль по нему. Теоретически метод должен возвращать true при условии, что введенный пароль правильный, но он возвращает false.

В чем может быть проблема?


person RacketyGnome300    schedule 02.11.2017    source источник
comment
Кажется действительно странным писать собственный слой модели. Почему бы вместо этого не использовать что-то вроде Sequel?   -  person tadman    schedule 02.11.2017
comment
Мне было бы интересно познакомиться с ним поближе. Спасибо за предложение   -  person RacketyGnome300    schedule 03.11.2017


Ответы (1)


При аутентификации вы, похоже, не хешируете входящий пароль. Это потому, что вы выполняете @password == password, где @password - это пароль в виде простого текста String (из User#initialize из post '/login').

Вы должны перевернуть сравнение, чтобы оно использовало BCrypt::Password#==: password == @password.

person Andrew Marshall    schedule 02.11.2017