Perl Dancer2 认证密码管理

Perl Dancer2 Authentication Password Management

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

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

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

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

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

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

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

Usually you'll want to let the built-in login handling code deal with authenticating users, but in case you need to do it yourself, this keyword accepts a username and password ...

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

我自己没有使用过这个模块,但在我看来,所有散列和加密的东西都应该由 authentication providers and if there's not one that covers the case you use, then you can write one yourself.

之一处理

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

首先,我将回应 "you almost certainly don't need to be using authenticate_user()" 评论。该插件可以为您处理所有这些。

然而,"it doesn't hash it"是错误的;这是它的工作原理。这 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() 将 return 一个关于登录用户信息的 hashref(并且因为 路线代码有require_login,这里保证有一个 点,所以你不需要检查)。

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