symfony5目前有以下5种授权机制:
# ...
x509:
# ...
remote_user:
# ...
guard:
# ...
form_login:
# ...
form_login_ldap:
# ...
json_login:
# ...
http_basic:
# ...
http_basic_ldap:
# ...
http_digest:
symfony5.4以后和5.2是不一样的:
- https://symfony.com/doc/5.4/security/custom_authenticator.html //这个就是官方文档说的新的认证系统
- https://symfony.com/doc/5.2/security/guard_authentication.html //旧的认证系统
旧的认证系统:
config/security.yaml
enable_authenticator_manager: false
main:
guard:
authenticators:
- App\Security\TokenAuthenticator //这个Authenticator 必须extends Guard相关的interface,已经被弃用了
新的认证系统:
config/security.yaml
enable_authenticator_manager: true
main:
custom_authenticators:
- App\Security\TokenAuthenticator //这个Authenticator extends 自 AbstractAuthenticator
上面新旧两种方式,对于路由而言,加了#[IsGranted('ROLE_USER')],生效的原理都是各自的Authenticator里的 supports 返回true, 后续验证[旧:checkCredentials 新:authenticate]成功, 只要返回成功,那么#[IsGranted('ROLE_USER')]就会生效,默认登录后的用户都有ROLE_USER这个角色.
//下面是一个新的认证的一个Authenticator
class ApiTokenAuthenticator extends AbstractAuthenticator
{
public function __construct(private EntityManagerInterface $em){}
public function supports(Request $request): ?bool
{
return $request->headers->has('authorization');
// TODO: Implement supports() method.
}
//本地测试发现,这个验证完成以后会向 session 写入用户token信息(UsernamePasswordToken),
public function authenticate(Request $request)
{
$apiToken = $request->headers->get('authorization');//这里弄得比较简单,直接在authorization里传递了用户的 email 地址作为 apiToken
if (null === $apiToken) {
// The token header was empty, authentication fails with HTTP Status
// Code 401 "Unauthorized"
throw new CustomUserMessageAuthenticationException('No API token provided');
}
// TODO: Implement authenticate() method.
return new SelfValidatingPassport(new UserBadge($apiToken, (function($token){
return $this->em->getRepository(User::class)->findOneBy(['email'=>$token]);
})->bindTo($this)));// 匿名函数的参数$token 即为 $apiToken
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
// TODO: Implement onAuthenticationSuccess() method.
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
// TODO: Implement onAuthenticationFailure() method.
return null;
}
}
关于IsGranted:
这个类是symfony的一个拓展,主要用于处理授权请求,可以有如下格式:
①#[IsGranted('ROLE_USER', message: 'You are not allowed to access the admin dashboard.', statusCode: 421)]
②其它用法是,还在研究中
通过异常监听可以捕获这个异常请求:
if ($throwable instanceof AccessDeniedException && $event->getRequest()->isXmlHttpRequest()) {
$data = [
'code' => 1,
'msg' => $throwable->getMessage(),
'data' => [],
];
$event->setResponse(new JsonResponse($data, $throwable->getCode()));
}
