【问题标题】:Perl Dancer2 Authentication Password ManagementPerl Dancer2 认证密码管理
【发布时间】:2018-02-07 14:24:43
【问题描述】:

所以任何使用过 perl dancer 的人都知道,要在登录时验证用户身份,您可以调用 authenticate_user

authenticate_user(
    params->{username}, params->{password}
);

这是 Auth::Extensible 插件的一部分。

在我看来,它鼓励使用纯文本存储密码!当然,您可以先对密码进行哈希处理,然后确保存储的密码是相同的哈希值,但这似乎更像是一种解决方法,我发现不能保证有效。我只有使用不应使用的 sha1 才能使它工作。我想使用 Bcrypt,但密码短语根本不匹配。可能是奇怪的字符不匹配我不确定。

问题是使用 dancer Passphrase 插件,我已经可以验证用户名和密码,甚至不需要依靠 authenticate_user 来验证它们。但是为了让舞者框架考虑登录用户,您仍然必须调用必须传递密码的 authenticate_user。

我完全被困住了。我很好奇其他人是如何设法在 dancer2 中使用正确的密码管理的?

【问题讨论】:

  • 看起来您甚至没有浏览过Dancer2::Plugin::Auth::Extensible 文档。
  • 在阅读了我能找到的所有文档后,我只在这样的地方发帖作为最后的手段。如果你只想给出一个典型的 rtfm 类型的响应,至少用一些推理来支持它,否则“看起来你甚至没有浏览过”这个问题。
  • 您从哪里得到密码需要以纯文本形式存储的想法?您显示的代码采用用户提供的凭据。它们显然是纯文本,但它们没有存储在任何地方,只是通过网络接收。 authenticate_user 将在后台处理哈希和比较。它是如何做到的是完全透明的。它附带了许多不同的提供者,但如果你需要其他东西,你也可以自己推出。
  • 为了澄清我正在使用“提供者:'数据库'”,所以我有一个带有用户表的数据库。我说它鼓励纯文本密码存储的原因是因为 authenticate_user 不会进行身份验证,除非 params->{password} 与数据库中的内容完全匹配。它不会散列它。但是 - "user_password username => 'jbloggs', new_password => 'secret'" 会在存储之前在 sha512 中对其进行哈希处理。

标签: perl authentication hash passwords dancer


【解决方案1】:

首先,我将回应“您几乎可以肯定不需要使用authenticate_user()”cmets。该插件可以为您处理所有这些。

但是,“它不散列”是错误的;这是它的工作原理。这 authenticate_user 关键字循环通过所有配置的身份验证领域,并且对于 每一个,询问提供者的authenticate_user() 方法看它是否接受 用户名和密码。 Database 提供者(和其他)获取 从数据库记录,并使用$self->match_password()(来自 Provider role) 进行验证;该代码检查存储的密码是否来自 数据库以{scheme} 开头,如果是,则使用 Crypt::SaltedHash->validate 验证用户提供的密码(在 纯文本,因为它只是通过网络进来的)匹配存储的,散列的 密码(下面代码中的$correct是存储的密码):

if ( $correct =~ /^{.+}/ ) {

    # Looks like a crypted password starting with the scheme, so try to
    # validate it with Crypt::SaltedHash:
    return Crypt::SaltedHash->validate( $correct, $given );
}

所以,是的,如果您在数据库中存储的密码经过哈希处理,那么它将匹配 如果提供的密码与该哈希匹配。

关于存储的散列密码应该是什么样子的示例,这里是 捆绑的generate-crypted-password 实用程序的输出:

[davidp@supernova:~]$ generate-crypted-password 
Enter plain-text password ?> hunter2
Result: {SSHA}z9llSLkkAXENw8FerEchzRxABeuJ6OPs

请参阅Crypt::SaltedHash doco 了解有关哪些算法的详细信息 它支持,以及它使用的格式(“来自 RFC-3112 和 通过使用不同的数字算法进行扩展")。

请记住,authenticate_user 背后的代码正是所使用的 在引擎盖下为您服务。

对于让插件为您完成工作的示例,请考虑:

get '/secret' => require_login sub {
    my $user = logged_in_user();
    return "Hi, $user->{username}, let me tell you a secret";
};

...就是这样。 require_login 表示插件将检查 如果用户已登录,如果未登录,则将其重定向到登录页面 登录。你不需要自己打电话给authenticate_user,你 不需要设置任何会话变量或任何东西。 logged_in_user() 将返回有关登录用户信息的 hashref(并且因为 路线代码有require_login,这里肯定有一个 点,所以你不需要检查)。

如果您需要检查他们是否有合适的角色,而不仅仅是他们 已登录,然后查看文档中的require_role

【讨论】:

    【解决方案2】:

    Dancer2::Plugin::Auth::Extensible 的文档中,authenticate_user() 的描述说:

    通常你会想让内置的登录处理代码处理用户身份验证,但如果你需要自己做,这个关键字接受用户名和密码......

    这对我来说强烈暗示你根本不应该调用这个函数,除非你在做一些特别聪明的事情。

    我自己没有使用过这个模块,但在我看来,所有散列和加密的东西都应该由authentication providers 之一处理,如果没有一个涵盖你使用的情况,那么你可以@ 987654323@.

    每当我需要为 Dancer 应用程序存储安全密码时,我都会联系 Dancer2::Plugin::Passphrase。我想知道是否应该考虑为它编写一个 Auth::Extensible 样式的身份验证提供程序。

    【讨论】:

    • 正确的加密内容应该由身份验证提供者处理。 Auth::Extensible::Provider::Database 的文档说使用了 Crypt::SaltedHash。然而,authenticate_user 似乎仍然只匹配数据库中的纯文本密码。我最终使用 Dancer2::Plugin::Passphrase 自己进行身份验证,但我确定我要做的并不是什么特别需要这种工作水平的事情。
    • @jeffez:但是你为什么打电话给authenticate_user()?对于大多数用途来说,这是不必要的。
    • 我的理解是,authenticate_user() 用于在添加会话变量登录用户之前检查用户名和密码。这就是我所需要的,但密码只会匹配纯文本,默认情况下,Auth::Extensible::Provider::Database 文档不应该发生这种情况。我最终编写了自己的用户名/密码匹配,但这有点违背“约定优于配置”。
    • 我的理解是,authenticate_user() 用于在添加会话变量登录用户之前检查用户名和密码。 那我只能建议你采取一个仔细看看the documentation。在正常使用中,这一切都为您处理,您无需自己致电authenticate_user()
    猜你喜欢
    • 2020-05-07
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多