Дивна проблема з розробкою valid_password?


78

Протягом останніх 2 годин я намагався налагодити дивну проблему в devise, яка не дозволяє мені увійти.

Ось речі, про які я теж маю на увазі:

password 
=> 'vinodsobale'

password == 'vinodsobale'
=> true

resource.valid_password?(password)

=> false

resource.valid_password?('vinodsobale')

=> true

Також додаємо знімок екрана:

введіть тут опис зображення Примітка: Я увімкнув налагоджувач всередині devise, тому наведений вище код є внутрішнім кодом.

Для мене це виглядає як проблема у Devise.secure_compare.


2
Відкрити випуск GitHub? Бажано з відтворюваним тестом.
vemv

4
@Viren - я не маю уявлення про рубін чи придумую, але я б перевірив кодування даного пароля.
MByD

3
Чи можете ви зробити це password.encodingі повідомити нам результат? Це єдине, про що я можу подумати, щоб там помилитися. Ви також можете пограти ::BCrypt::Engine.hash_secret(password, salt)і порівняти це з фактично збереженим хешем. Для цього порівняння text.bytesтакож може стати в нагоді.
Рудольф

4
Чи можете ви перевірити password.bytesі 'vinodsobale'.bytesпросто переконатися?
Рудольф

3
@ lad2025, що ви маєте на увазі під словом "врятований"? Це password? Якщо це так, його NULL character \0слід закодувати в Unicode і password == 'vinodsobale'не повертати true.
вутран,

Відповіді:


3

Ця проблема виникла через відому помилку корупції рядків у Ruby 2.2.0, яку було виправлено у 2.2.2.

Як описано в повідомленні про помилку , псування відбулося , коли BCrypt називається конкретний API-струнний створення з його розширення C, який Розробляє v3.3.0 спрацьовує шляхом виклику ::BCrypt::Engine.hash_secretз Devise::Models::DatabaseAuthenticatable#valid_password?методу. Розробляють конкретний обхідний шлях для цієї помилки був опублікований в v3.5.0.

Рішення полягає в тому, щоб:

  • Понизити < 2.2.0версію Ruby до або оновіть до >= 2.2.2;
  • Розробити оновлення до >= 3.5.0.

0

Як щодо

resource.valid_password?(password.to_s)

Сподіваюся, це допоможе Вам.


3
Будь ласка, відредагуйте свою публікацію та поясніть, чому це могло б працювати.
Рохіт Гупта,

Чому, на вашу думку, це буде працювати, я бачу багато проблем з цим, по-перше, я вже згадував, тобто password == 'vinodsobale' збіги. Це було, якщо vinodsobleмає тип string(що ми всі можемо бачити), то passwordце теж stringтак, .to_sзвичайно, не даючи нічого іншого. По-друге, код, який ви щойно згадали, є частиною внутрішнього коду розробника, як ви хочете реалізувати це, наприклад, відкрити код пристрою та виправити мавпу.
Viren

1
Можливо, оператор рівних автоматично викликає метод to_s, якщо праворуч є недійсний тип. Але я лише здогадуюсь. Ви спробували?
Пабло Джомер

це правдоподібне пояснення.
sevenseacat

2
Ви використовували password == 'vinosobale'. Не могли б ви спробувати password === 'vidodsobale' матчі? Чи не могли б ви прочитати це запитання - stackoverflow.com/questions/7156955/… ?
Сергій Назаревич

0

Devise DatabaseAuthenticatable#valid_password?використовує метод, який називається " Encryptor::compareберуть 2 об'єкти", поточний збережений пароль і новий пароль, який ви хочете порівняти. Я вважаю, що у цього методу є побічний ефект, який змінює другий параметр посередині, і замість цього він змінить об'єкт один раз він буде змінений двічі, що призведе до помилкового результату, тому це може спрацювати, якщо ви передали продубльований об'єкт пароля. Ви можете спробувати використовуватиvalid_password? password.dup


Якщо це так, чому модифікація не відбувається, коли рядок подається resource.valid_password?('vinodsobale')кожного разу, коли я запускав це, він раніше працював, іreturn true
Вірен,

0

Це може бути проблема з кодуванням між першоджерелом та консоллю. Якщо ви запустите password.codepoints, ви зможете побачити фактичне кодування. Запуск .codepointsна необробленому рядку "пароль" повинен повернутися [112, 97, 115, 115, 119, 111, 114, 100].

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.