弱化security.context服务 ¶
这是symfony2.6的主要改进点之一。好在这并不会影响你的代码,因为它维持了向后兼容(译注:3.0都会取消)。多数情况下,考虑到为将来的symfony版本做好准备,你应该学习操作security的新方法。
做出如此改变的原因,是因为当你注入SecurityContext
到其他服务中时,特别是那些跟doctrine有关的,你可能会陷入“循环引用(circular reference)”进而导致异常。
经过sf社区的讨论,大家一致认为SecurityContext
在仅为取出简单的Token/User时存在过度依赖。这就是为什么从2.6起,security.context服务被弱化并被分为两个全新服务的原因:security.authorization_checker
和security.token_storage
.
由于100%向下兼容,你毋须更新现有程序代码。不过,万一你需要这样做,进行如下微小变化:
1 2 3 4 5 6 7 8 9 | // Symfony 2.5
$user = $this->get('security.context')->getToken()->getUser();
// Symfony 2.6
$user = $this->get('security.token_storage')->getToken()->getUser();
// Symfony 2.5
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { ... }
// Symfony 2.6
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { ... } |
作为这项改变的附加奖励,则是对security相关常量的简化,大幅方便了记忆:
1 2 3 4 5 6 7 | // Symfony 2.5
use Symfony\Component\Security\Core\SecurityContextInterface;
if ($security->has(SecurityContextInterface::AUTHENTICATION_ERROR)) { ... }
// Symfony 2.6
use Symfony\Component\Security\Core\Security;
if ($security->has(Security::AUTHENTICATION_ERROR)) { ... } |
最后,此一改进点同时也弱化了app.security
这个Twig全局模板变量。你应该使用app.user
变量以及is_granted()
函数。
用于简化密码加密的新服务 ¶
作为一个DX开发体验建议的反馈,symfony2.6引入了全新的security.password_encoder
服务,用于给密码加密:
1 2 3 4 5 6 7 8 9 10 | // Symfony 2.5
$user = new Acme\UserBundle\Entity\User();
$factory = $this->container->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword($plainTextPassword, $user->getSalt());
// Symfony 2.6
$user = new Acme\UserBundle\Entity\User();
$encoder = $this->container->get('security.password_encoder');
$password = $encoder->encodePassword($user, $plainTextPassword); |
为security firewall添加了基于REMOTE_USER的监听 ¶
某些Apache服务模块(auth_kerb
, auth_cas
等),通过被称为REMOTE_USER
的环境变量来提供username
。因此,Symfony 2.6引入了一个新的验证监听,用于此变量。
1 2 3 4 5 6 7 | # app/config/security.yml
security:
firewalls:
secured_area:
pattern: ^/
remote_user:
provider: your_user_provider |
添加了一个security error helper服务 ¶
自定义一个登陆表单,这在symfony中是相当容易的,但代码层面却相对冗余一些:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // Symfony 2.5
public function loginAction(Request $request)
{
$session = $request->getSession();
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContextInterface::AUTHENTICATION_ERROR
);
} elseif (null !== $session && $session->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
$error = $session->get(SecurityContextInterface::AUTHENTICATION_ERROR);
$session->remove(SecurityContextInterface::AUTHENTICATION_ERROR);
} else {
$error = '';
}
$lastUsername = (null === $session) ? '' : $session->get(SecurityContextInterface::LAST_USERNAME);
return $this->render(
'AcmeSecurityBundle:Security:login.html.twig',
array(
'last_username' => $lastUsername,
'error' => $error,
)
);
} |
那么作为对DX开发体验#11147的响应,我们决定在Symfony 2.6中引入一个全新的helper,它令人惊异地把表单action中的代码戏剧化地减少到了如下程度:
1 2 3 4 5 6 7 8 9 10 | // Symfony 2.6
public function loginAction()
{
$helper = $this->get('security.authentication_utils');
return $this->render('AcmeSecurityBundle:Security:login.html.twig', array(
'last_username' => $helper->getLastUsername(),
'error' => $helper->getLastAuthenticationError(),
));
} |