Symfony 的 Security 体系很强,也正因为强,所以很多人一开始容易怕。
其实你把它当成三层就行:
1. 你是谁?
= Authentication 认证
2. 你现在经过哪道安检?
= Firewall 防火墙
3. 你对这份材料有没有这个动作权限?
= Authorization 授权 / Voter一个典型配置长这样:
security:
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_profiler|_wdt|assets|build)/
security: false
main:
lazy: true
provider: app_user_provider
form_login: true
logout: true
access_control:
- { path: ^/admin, roles: ROLE_REVIEWER }这里最重要的不是记语法,而是理解它的城区含义:
provider:通行证档案从哪查firewall:这次请求经过哪道安检门access_control:某些区域先做粗粒度门禁
然后更细的权限判断,交给 Voter:
<?php
namespace App\Security\Voter;
use App\Entity\BusinessPermit;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
final class PermitVoter extends Voter
{
protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, ['PERMIT_VIEW', 'PERMIT_EDIT'], true)
&& $subject instanceof BusinessPermit;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
if (in_array('ROLE_REVIEWER', $user->getRoles(), true)) {
return true;
}
return $attribute === 'PERMIT_VIEW';
}
}这背后其实就是一个非常成熟的政务脑回路:
粗粒度门禁
= 哪些人能进哪栋楼
细粒度投票
= 对这份具体材料,他能看?能改?能批?还要记住一条很实用的官方最佳实践:
如果不是确实存在两套完全不同的认证体系,尽量只有一个主 firewall。
多防火墙会让整座城区的通行逻辑变得很绕。