ruby - Meteor 使用 bcrypt 验证来自不同服务器的电子邮件/密码

标签 ruby authentication meteor devise meteor-accounts

我想让我的 meteor 用户通过 ruby 应用程序登录。

我在哪里

  • 我有两个网站,都在同一个域中,都共享同一个 MongoDB。
  • 一个是带有accounts-password(使用bcrypt)的METEOR-app
  • 另一个是 RUBY ON RAILS 应用程序,它使用 devise(也使用 bcrypt)进行身份验证。
  • 我可以在这两个应用程序上分别注册和登录。

当我将 encrypted_pa​​ssword 从 Meteor 的“bcrypt”字段传输(复制/粘贴)到 Ruby 的“encrypted_pa​​ssword”并尝试登录时,我被拒绝了。反之亦然。然后我在我的 ruby​​ 应用程序中重新创建了 meteor 应用程序的那种加盐(在它们被比较之前的 SHA-256 纯密码散列)。

(这里是 meteor accounts-password 源文件(https://github.com/meteor/meteor/blob/oplog-backlog-on-1.0.3.1/packages/accounts-password/password_server.js))

这是我的 Ruby 实现:

class BCryptSHA256Hasher < Hasher
  def initialize
    @algorithm = :bcrypt_sha256
    @cost = 10
    @digest = OpenSSL::Digest::SHA256.new
  end

  def salt
    BCrypt::Engine.generate_salt(@cost)
  end

  def get_password_string(password)
    @digest.digest(password) unless @digest.nil?
  end

  def encode(password, salt)
    password = get_password_string(password)
    hash = BCrypt::Engine.hash_secret(password, salt)
    return hash
  end

  def verify(password, encoded)
    password_digest = get_password_string(password)
    hash = BCrypt::Engine.hash_secret(password_digest, encoded)
    # password = "asdfasdf"
    # encoded  = "$2a$10$FqvtI7zNgmdWJJG1n9JwZewVYrzEn38JIxEGwmMviMsZsrCmYHqWm"
    # hash     = "$2a$10$FqvtI7zNgmdWJJG1n9JwZe22XU1hRDSNtHIrnYve9FbmjjqJCLhZi"
    # constant_time_comparison:
    constant_time_compare(encoded, hash)
  end

  def constant_time_compare(a, b)
    check = a.bytesize ^ b.bytesize
    a.bytes.zip(b.bytes) { |x, y| check |= x ^ y }
    check == 0
  end

end

这是一个有效的 User 文档,两个服务器都将使用它:

{
  "_id": "g4BPfpavJGGTNgJcE",
  "authentication_token": "iZqmCsYS1Y9Xxh6t22-X",
  "confirmed_at": new Date(1457963598783),
  "createdAt": new Date(1457963456581),
  "current_sign_in_at": new Date(1457966356123),
  "current_sign_in_ip": "127.0.0.1",
  "email": "demo@demo.com",
  "emails": [
    {
      "address": "demo@demo.com",
      "verified": true
    }
  ],
  "encrypted_password": "$2a$10$7/PJw51HgXfzYJWpaBHGj.QoRCTl0E29X0ZYTZPQhLRo69DGi8Xou",
  "failed_attempts": 0,
  "last_sign_in_at": new Date(1457966356123),
  "last_sign_in_ip": "127.0.0.1",
  "profile": {
    "_id": ObjectId("56e6c1e7a54d7595e099da27"),
    "firstName": "asdf",
    "lastName": "asdf"
  },
  "reset_password_sent_at": null,
  "reset_password_token": null,
  "services": {
    "_id": ObjectId("56e6c1e7a54d7595e099da28"),
    "password": {
      "bcrypt": "$2a$10$7/PJw51HgXfzYJWpaBHGj.QoRCTl0E29X0ZYTZPQhLRo69DGi8Xou"
    },
    "resume": {
      "loginTokens": [

      ]
    }
  },
  "sign_in_count": 1,
  "updated_at": new Date(1457966356127),
  "username": "mediatainment"
}

最佳答案

我认为@maxpleaner 的评论是处理身份验证的最佳方式。但如果真的需要单独对用户进行身份验证,那么只需猴子补丁设计即可。

config/initializers/devise_meteor_adapter.rb

module DeviseMeteorAdapter
  def digest(klass, password)
    klass.pepper = nil
    password = ::Digest::SHA256.hexdigest(password)
    super
  end

  def compare(klass, hashed_password, password)
    klass.pepper = nil
    password = ::Digest::SHA256.hexdigest(password)
    super
  end
end

Devise::Encryptor.singleton_class.prepend(DeviseMeteorAdapter)

警告:未经测试。

关于ruby - Meteor 使用 bcrypt 验证来自不同服务器的电子邮件/密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35951065/

相关文章:

ruby - 按第二个值对二维数组进行排序

javascript - y 轴的 Highcharts 复选框

ruby - 如何在可变参数列表的末尾传递散列?

authentication - 基于接受的eula的Symfony2自定义用户检查器

meteor - 如何在meteorjs模板中监听表单的提交事件?

ruby-on-rails - 安装最新版本后显示较旧的 Ruby 版本

reactjs - 使用NextJS和Auth0时如何添加共享布局?

javascript - 如何使用在身份验证 header 中保存为 httpOnly cookie 的访问 token ?

javascript - 如何在使用 Instagram API 时在 Meteor 中请求、存储和使用访问 token

javascript - 如何根据集合中的数据显示html字段?