身份验证
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 3.4,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
身份验证
当请求指向安全区域时,防火墙映射中的一个侦听器能够从当前数据中提取用户的凭据请求对象时,它应该创建一个令牌,其中包含这些凭据。侦听器应该做的下一件事是请求身份验证管理器验证给定的令牌,并返回通过身份验证令牌,如果发现所提供的凭证是有效的。侦听器然后应该使用存储经过身份验证的令牌令牌存储:
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 37 38 39 40 41 42 43 44 45
使用ob娱乐下载\组件\HttpKernel\事件\GetResponseEvent;使用ob娱乐下载\组件\安全\核心\身份验证\AuthenticationManagerInterface;使用ob娱乐下载\组件\安全\核心\身份验证\令牌\存储\TokenStorageInterface;使用ob娱乐下载\组件\安全\核心\身份验证\令牌\UsernamePasswordToken;使用ob娱乐下载\组件\安全\Http\防火墙\ListenerInterface;类SomeAuthenticationListener实现了ListenerInterface{/ * * *@varTokenStorageInterface * /私人$tokenStorage;/ * * *@varAuthenticationManagerInterface * /私人$authenticationManager;/ * * *@varstring唯一标识安全区域*/私人$providerKey;/ /……公共函数处理(GetResponseEvent$事件){$请求=$事件->getRequest ();$用户名=……;$密码=……;$unauthenticatedToken=新UsernamePasswordToken ($用户名,$密码,$这->providerKey);$authenticatedToken=$这->authenticationManager->验证($unauthenticatedToken);$这->tokenStorage->setToken ($authenticatedToken);}}
请注意
令牌可以是任何类,只要它实现了TokenInterface.
身份验证管理器
的实例AuthenticationProviderManager:
12 3 4 5 6 7 8 9 10 11 12 13 14
使用ob娱乐下载\组件\安全\核心\身份验证\AuthenticationProviderManager;使用ob娱乐下载\组件\安全\核心\异常\AuthenticationException;// Symfony\Compoob娱乐下载nent\Security\Core\Authentication\Provider\AuthenticationProviderInterface的实例$供应商=[…];$authenticationManager=新AuthenticationProviderManager ($供应商);试一试{$authenticatedToken=$authenticationManager->验证($unauthenticatedToken);}抓(AuthenticationException$异常) {//认证失败}
的AuthenticationProviderManager
实例化时,接收多个身份验证提供者,每个提供者支持不同类型的令牌。
请注意
您可以编写自己的身份验证管理器,它只需要实现即可AuthenticationManagerInterface.
身份验证提供者
每个提供者(因为它实现了AuthenticationProviderInterface)有一个支持()所采用的方法AuthenticationProviderManager
可以确定它是否支持给定的令牌。如果是这种情况,管理器将调用提供者的服务authenticate ()方法。此方法应返回已验证的令牌或抛出AuthenticationException(或任何其他扩展它的异常)。
通过用户名和密码认证用户
身份验证提供者将尝试根据用户提供的凭据对用户进行身份验证。通常是用户名和密码。大多数web应用程序存储用户的用户名和用户密码的散列,并结合随机生成的salt。这意味着平均身份验证将包括从用户数据存储中获取salt和散列密码,将用户刚刚提供的密码(例如使用登录表单)与salt进行散列,并将两者进行比较,以确定给定的密码是否有效。
类提供了此功能DaoAuthenticationProvider.对象中获取用户的数据UserProviderInterface,使用PasswordEncoderInterface创建密码散列,如果密码有效,则返回一个已验证的令牌:
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
使用ob娱乐下载\组件\安全\核心\身份验证\提供者\DaoAuthenticationProvider;使用ob娱乐下载\组件\安全\核心\编码器\EncoderFactory;使用ob娱乐下载\组件\安全\核心\用户\InMemoryUserProvider;使用ob娱乐下载\组件\安全\核心\用户\UserChecker;$userProvider=新InMemoryUserProvider ([“管理”= > [//密码为"foo"“密码”= >“5 fz2z8qika7utz4bykoc + GsReLf569mSKDsfods6LYQ8t + a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg = =”,“角色”= > [“ROLE_ADMIN”],],]);//一些额外的检查:帐户是否启用,锁定,过期等。$userChecker=新UserChecker ();//密码编码器的数组(见下面)$encoderFactory=新EncoderFactory(…);$daoProvider=新DaoAuthenticationProvider ($userProvider,$userChecker,“secured_area”,$encoderFactory);$daoProvider->验证($unauthenticatedToken);
请注意
上面的示例演示了“内存中”用户提供程序的使用,但您可以使用任何用户提供程序,只要它实现了即可UserProviderInterface.方法也可以让多个用户提供程序尝试查找用户的数据ChainUserProvider.
密码编码器工厂
的DaoAuthenticationProvider使用编码器工厂为给定类型的用户创建密码编码器。这允许您针对不同类型的用户使用不同的编码策略。默认的EncoderFactory接收编码器数组:
12 3 4 5 6 7 8 9 10 11 12 13 14
使用Acme\实体\LegacyUser;使用ob娱乐下载\组件\安全\核心\编码器\EncoderFactory;使用ob娱乐下载\组件\安全\核心\编码器\MessageDigestPasswordEncoder;使用ob娱乐下载\组件\安全\核心\用户\用户;$defaultEncoder=新MessageDigestPasswordEncoder (“sha512”,真正的,5000);$weakEncoder=新MessageDigestPasswordEncoder (md5的,真正的,1);$编码器=[用户]::类= >$defaultEncoder, LegacyUser::类= >$weakEncoder,/ /……];$encoderFactory=新EncoderFactory ($编码器);
每个编码器都应该实现PasswordEncoderInterface或者是一个带有a的数组类
和一个参数
键,该键允许编码器工厂仅在需要时构造编码器。
创建自定义密码编码器
有许多内置的密码编码器。但如果你需要创建自己的,它只需要遵循以下规则:
- 类必须实现PasswordEncoderInterface;
的实现encodePassword ()而且isPasswordValid ()首先必须确保密码不太长,即密码长度不超过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
使用ob娱乐下载\组件\安全\核心\编码器\BasePasswordEncoder;使用ob娱乐下载\组件\安全\核心\异常\BadCredentialsException;类FoobarEncoder扩展BasePasswordEncoder{公共函数encodePassword($生,$盐){如果($这->isPasswordTooLong ($生)) {扔新BadCredentialsException (无效的密码。);}/ /……}公共函数isPasswordValid($编码,$生,$盐){如果($这->isPasswordTooLong ($生)) {返回假;}/ /……}}
使用密码编码器
当getEncoder ()方法调用时,将user对象作为其第一个参数,则它将返回类型为的编码器PasswordEncoderInterface应该用来编码这个用户的密码:
12 3 4 5 6 7 8 9 10 11 12 13 14
// Acme\Entity\LegacyUser$用户=……;//提交的密码,例如注册时$plainPassword=……;$编码器=$encoderFactory->getEncoder ($用户);//返回$weakEncoder(见上文)$encodedPassword=$编码器->encodePassword ($plainPassword,$用户->getSalt ());$用户->向setPassword ($encodedPassword);/ /……保存用户
现在,当你想检查提交的密码是否正确时(例如,当你试图登录时),你可以使用:
1 2 3 4 5 6 7 8 9 10 11
//获取Acme\Entity\LegacyUser$用户=……;//提交的密码,例如从登录表单$plainPassword=……;$validPassword=$编码器->isPasswordValid ($用户->getPassword (),//编码的密码$plainPassword,//提交的密码$用户->getSalt ());
验证事件
安全组件提供了4个相关的身份验证事件:
的名字 | 事件不断 | 参数传递给监听器 |
---|---|---|
security.authentication.success | AuthenticationEvents: AUTHENTICATION_SUCCESS |
AuthenticationEvent |
security.authentication.failure | AuthenticationEvents: AUTHENTICATION_FAILURE |
AuthenticationFailureEvent |
security.interactive_login | SecurityEvents: INTERACTIVE_LOGIN |
InteractiveLoginEvent |
security.switch_user | SecurityEvents: SWITCH_USER |
SwitchUserEvent |
认证成功和失败事件
当提供者对用户进行身份验证时,asecurity.authentication.success
事件被分派。但是要注意-这个事件会触发,例如,在每一个如果您有基于会话的身份验证,则请求。看到security.interactive_login
下面如果你需要做些什么当用户实际上登录。
当提供者尝试身份验证但失败时(即抛出AuthenticationException
),一个security.authentication.failure
事件被分派。你可以听security.authentication.failure
事件,以便记录失败的登录尝试。