密码哈希和验证
编辑本页密码哈希和验证
大多数应用程序使用密码登录用户。这些密码应该被散列以安全地存储它们。ob娱乐下载Symfony的PasswordHasher组件提供了安全散列和验证密码的所有实用程序。
确保通过以下命令安装:
1
$作曲家需要symfony/密码散列ob娱乐下载器
配置密码散列器
在对密码进行散列之前,必须使用password_hashers
选择。您必须配置散列算法还有一些算法的选择:
- YAML
- XML
- PHP
- 独立使用
12 3 4 5 6 7 8 9 10 11 12
#配置/包/ security.yaml安全:#……password_hashers:# User类(和子类)的默认选项的自动散列应用实体\ \用户:“汽车”为所有PasswordAuthenticatedUserInterface实例设置自定义选项ob娱乐下载Symfony \ \安全\ \用户\ PasswordAuthenticatedUserInterface核心组件:算法:“汽车”成本:15
在本例中,使用“auto”算法。这个散列器自动选择系统上可用的最安全的算法。结合迁移密码,这允许您始终以最安全的方式保护密码(即使在将来的PHP发行版中引入了新的算法)。
在本文的后面,您可以找到一个所有支持的算法的完整引用.
提示
散列密码是资源密集型的,并且需要时间来生成安全的密码散列。一般来说,这使您的密码哈希更安全。
但是,在测试中,安全散列并不重要,因此可以在中更改密码散列配置测验
更快地运行测试的环境:
- YAML
- XML
- PHP
12 3 4 5 6 7 8 9 10 11 12
#配置/包/测试/ security.yamlpassword_hashers:使用你的用户类名应用实体\ \用户:算法:明文#禁用哈希(只在测试中这样做!)#或使用尽可能低的值应用实体\ \用户:算法:汽车这个值应该与config/packages/security.yaml中的值相同成本:4# bcrypt的最低可能值time_cost:3.#氩的最低可能值memory_cost:10#氩的最低可能值
哈希密码
配置正确的算法后,可以使用UserPasswordHasherInterface
哈希和验证密码:
- 框架的使用
- 独立使用
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/ / src /控制器/ RegistrationController.php名称空间应用程序\控制器;/ /……使用ob娱乐下载\组件\HttpKernel\异常\AccessDeniedHttpException;使用ob娱乐下载\组件\PasswordHasher\切肉机\UserPasswordHasherInterface;类用户控件扩展AbstractController{公共函数登记(UserPasswordHasherInterface$passwordHasher){/ /……例如,从注册表单中获取用户数据$用户=新用户(…);$plaintextPassword=……;//哈希密码(基于安全。$user类的Yaml配置)$hashedPassword=$passwordHasher->hashPassword ($用户,$plaintextPassword);$用户->向setPassword ($hashedPassword);/ /……}公共函数删除(UserPasswordHasherInterface$passwordHasher,用户界面$用户){/ /……例如,从“确认删除”对话框中获取密码$plaintextPassword=……;如果(!$passwordHasher->isPasswordValid ($用户,$plaintextPassword)) {扔新AccessDeniedHttpException ();}}}
重置密码
使用MakerBundle而且ob娱乐下载SymfonyCastsResetPasswordBundle,您可以创建一个安全的开箱即用的解决方案来处理忘记密码。首先,安装SymfonyCastsReob娱乐下载setPasswordBundle:
1
$Composer需要symfonyob娱乐下载casts/reset-password-bundle
然后,使用: reset-password
命令。这会问你一些关于你的应用程序的问题,并生成你需要的所有文件!之后,您将看到一条成功消息和您需要执行的任何其他步骤的列表。
1
$PHP bin/console make:重置密码
控件,可以自定义重置密码包的行为reset_password.yaml
文件。有关配置的更多信息,请参阅ob娱乐下载SymfonyCastsResetPasswordBundle指南。
迁移密码
为了保护密码,建议使用最新的哈希算法存储密码。这意味着如果您的系统支持更好的散列算法,则用户的密码应该是重复。使用较新的算法和存储。这是可能的migrate_from
选择:
使用“migrate_from”配置一个新的散列器
当有更好的散列算法可用时,您应该保留现有的散列器,重命名它,然后定义新的散列器。设置migrate_from
新散列器上的选项指向旧的遗留散列器:
- YAML
- XML
- PHP
- 独立使用
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#配置/包/ security.yaml安全:#……password_hashers:#过去为某些用户使用的散列器遗留问题:算法:sha256encode_as_base64:假迭代:1应用实体\ \用户:#新的散列器及其选项算法:钠migrate_from:-bcrypt#使用“bcrypt”散列器和默认选项-遗产#使用上面配置的“遗留”散列器
这样设置:
- 新用户将使用新算法进行哈希;
- 每当用户登录时,其密码仍然使用旧算法存储,Symfony将使用旧算法验证密码,然后使用新算法重新哈希并更新密码。ob娱乐下载
提示
的汽车,本地的,bcrypt而且氩散列器使用以下列表自动启用密码迁移migrate_from
算法:
- PBKDF2(它使用hash_pbkdf2);
- 消息摘要(使用哈希)
两者都使用hash_algorithm
设置为算法。建议使用migrate_from
而不是hash_algorithm
,除非汽车使用Hasher。
升级密码
在成功登录后,Security系统将检查是否有更好的算法可用于散列用户的密码。如果是,它将使用新的散列对正确的密码进行散列。在使用自定义身份验证器时,必须使用PasswordCredentials
在安全的护照.
您可以通过实现这个新散列密码应该如何存储来启用升级行为:
在这之后,你就完成了,密码总是尽可能安全地散列!
请注意
在Symfony应用程序外部使用PasswordHasher组件时,必须手动使用ob娱乐下载PasswordHasherInterface: needsRehash ()
方法检查是否需要重新散列PasswordHasherInterface: hash ()
方法使用新算法重新散列明文密码。
使用Doctrine时升级密码
当使用实体用户提供商、实现PasswordUpgraderInterface在UserRepository
(见教义文档提供信息关于如何创建这个类(如果它还没有创建的话)。这个接口实现了存储新创建的密码哈希。
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ / src /仓库/ UserRepository.php名称空间应用程序\存储库;/ /……使用ob娱乐下载\组件\安全\核心\用户\PasswordUpgraderInterface;类UserRepository扩展EntityRepository实现了PasswordUpgraderInterface{/ /……公共函数upgradePassword(用户界面$用户、字符串$newHashedPassword):无效{//在User对象上设置新的散列密码$用户->向setPassword ($newHashedPassword);//在数据库上执行查询$这->getEntityManager ()->冲洗();}}
使用自定义用户提供程序时升级密码
如果你用的是定制用户提供程序,实现PasswordUpgraderInterface在用户提供程序中:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src /安全/ UserProvider.php名称空间应用程序\安全;/ /……使用ob娱乐下载\组件\安全\核心\用户\PasswordUpgraderInterface;类UserProvider实现了UserProviderInterface,PasswordUpgraderInterface{/ /……公共函数upgradePassword(用户界面$用户、字符串$newHashedPassword):无效{//在User对象上设置新的散列密码$用户->向setPassword ($newHashedPassword);/ /……保存新密码}}
从自定义散列触发密码迁移
如果使用自定义密码散列器,可以通过返回来触发密码迁移真正的
在needsRehash ()
方法:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src /安全/ CustomPasswordHasher.php名称空间应用程序\安全;/ /……使用ob娱乐下载\组件\PasswordHasher\切肉机\UserPasswordHasherInterface;类CustomPasswordHasher实现了UserPasswordHasherInterface{/ /……公共函数needsRehash(字符串$散列):保龄球{//检查当前密码是否使用过时的散列器$hashIsOutdated=……;返回$hashIsOutdated;}}
命名密码哈希器
通常,通过将密码散列器配置为应用于特定类的所有实例,可以对所有用户使用相同的密码散列器。另一种选择是使用“命名”散列器,然后选择您想动态使用的散列器。
默认情况下(如本文开头所示)汽车
算法用于应用实体\ \用户
.
对于普通用户来说,这可能已经足够安全了,但如果您希望管理员拥有更强大的算法呢汽车
成本更高。这可以通过命名哈希器来完成:
- YAML
- XML
- PHP
- 独立使用
1 2 3 4 5 6 7
#配置/包/ security.yaml安全:#……password_hashers:严厉的:算法:汽车成本:15
这将创建一个名为严厉的
.为了得到a用户
实例要使用它,类必须实现PasswordHasherAwareInterface.该接口只需要一个方法-getPasswordHasherName ()
-返回要使用的散列器的名称:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/ / src /实体/ User.php名称空间应用程序\实体;使用ob娱乐下载\组件\PasswordHasher\切肉机\PasswordHasherAwareInterface;使用ob娱乐下载\组件\安全\核心\用户\PasswordAuthenticatedUserInterface;使用ob娱乐下载\组件\安全\核心\用户\用户界面;类用户实现了用户界面,PasswordAuthenticatedUserInterface,PasswordHasherAwareInterface{/ /……公共函数getPasswordHasherName():哦?字符串{如果($这->isAdmin ()) {返回“苛刻”;}返回零;//使用默认散列器}}
如果您创建了自己的密码散列器,实现PasswordHasherInterface,你必须为它注册一个服务,以便使用它作为命名散列器:
- YAML
- XML
- PHP
1 2 3 4 5 6
#配置/包/ security.yaml安全:#……password_hashers:app_hasher:id:“Hasher App \安全\ \ MyCustomPasswordHasher”
这将创建一个名为app_hasher
从具有ID的服务应用Hasher \安全\ \ MyCustomPasswordHasher
.
支持算法
“自动”散列器
它会自动选择最好的可用散列器(目前是Bcrypt)。如果PHP或Symfob娱乐下载ony将来添加新的密码散列器,它可能会选择不同的散列器。
因此,散列密码的长度将来可能会改变,因此请确保为它们分配足够的空间进行持久化(varchar (255)
应该是个不错的设定)。
Bcrypt密码散列器
方法生成散列密码Bcrypt密码哈希功能.散列密码是60
字符很长,所以请确保为它们分配足够的空间进行持久化。此外,密码还包括加密盐在它们里面(每个新密码都会自动生成),所以你不必处理它。
它唯一的配置选项是成本
,取值范围为4-31
(在默认情况下,13
).每一个成本增量加倍的时间它需要对密码进行哈希。它是这样设计的,因此密码强度可以适应计算能力的未来改进。
您可以随时更改成本-即使您已经使用不同的成本散列了一些密码。新密码将使用新的代价进行哈希,而已经哈希的密码将使用哈希时使用的代价进行验证。
提示
使用BCrypt时,使测试更快的一个简单技术是将成本设置为4
中允许的最小值测验
环境配置。
钠密码散列器
它使用Argon2键推导函数.Argon2支持是在PHP 7.2中通过捆绑libsodium扩展。
散列后的密码为96
字符长,但是由于保存在结果散列中的散列要求,这在将来可能会改变,所以请确保分配足够的空间来持久化它们。此外,密码还包括加密盐在它们里面(每个新密码都会自动生成),所以你不必处理它。
创建自定义密码散列器
如果你需要创建自己的,它需要遵循以下规则:
- 类必须实现PasswordHasherInterface(您也可以实现LegacyPasswordHasherInterface如果你的哈希算法使用一个单独的盐);
的实现hash ()而且验证()必须验证密码长度不超过4096个字符。这是出于安全原因(参见cve - 2013 - 5750).
您可以使用isPasswordTooLong ()方法。
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/ / src /安全/厨师/ CustomVerySecureHasher.php名称空间应用程序\安全\切肉机;使用ob娱乐下载\组件\PasswordHasher\异常\InvalidPasswordException;使用ob娱乐下载\组件\PasswordHasher\切肉机\CheckPasswordLengthTrait;使用ob娱乐下载\组件\PasswordHasher\PasswordHasherInterface;类CustomVerySecureHasher实现了PasswordHasherInterface{使用CheckPasswordLengthTrait;公共函数哈希(字符串$plainPassword):字符串{如果($这->isPasswordTooLong ($plainPassword)) {扔新InvalidPasswordException ();}/ /……以安全的方式哈希普通密码返回$hashedPassword;}公共函数验证(字符串$hashedPassword、字符串$plainPassword):保龄球{如果(”= = =$plainPassword||$这->isPasswordTooLong ($plainPassword)) {返回假;}/ /……以安全的方式验证密码是否等于用户密码返回$passwordIsValid;}}
方法定义密码散列器id
设置:
- YAML
- XML
- PHP
1 2 3 4 5 6 7
#配置/包/ security.yaml安全:#……password_hashers:app_hasher:#你的自定义散列器的服务ID(使用默认services.yaml的FQCN)id:“Hasher App \安全\ \ MyCustomPasswordHasher”