指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub

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()));
}