如何在不使用Doctrine的情况下实现Symfony 5身份认证?
不依赖Doctrine实现Symfony 5.3 Authenticator-based 身份认证方案
以下是完整的落地步骤,全程不需要引入任何Doctrine相关组件:
1. 实现自定义User类
首先创建符合Symfony安全规范的User实体,不需要加任何Doctrine注解,直接实现UserInterface和PasswordAuthenticatedUserInterface两个接口即可:
<?php namespace App\Entity; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; class User implements UserInterface, PasswordAuthenticatedUserInterface { private $id; private $email; private $password; private $name; private $roles = []; // 自行添加各字段的getter、setter方法 public function getId(): ?int { return $this->id; } public function getEmail(): ?string { return $this->email; } public function getPassword(): ?string { return $this->password; } public function getName(): ?string { return $this->name; } public function getRoles(): array { $roles = $this->roles; $roles[] = 'ROLE_USER'; return array_unique($roles); } public function getUserIdentifier(): string { return (string) $this->email; } public function eraseCredentials() { // 不需要处理敏感数据的话留空即可 } }
2. 实现自定义UserProvider
创建自定义用户提供器,实现UserLoaderInterface接口,所有用户查询逻辑直接使用你项目现有数据库操作方式(PDO、自定义数据库层均可,以下用PDO做示例):
<?php namespace App\Security; use App\Entity\User; use Symfony\Component\Security\Core\Exception\UserNotFoundException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserLoaderInterface; class CustomUserProvider implements UserLoaderInterface { private $pdo; // 注入你项目的数据库连接实例即可,不需要用Doctrine public function __construct(\PDO $pdo) { $this->pdo = $pdo; } public function loadUserByIdentifier(string $identifier): UserInterface { $stmt = $this->pdo->prepare('SELECT id, email, password, name, roles FROM user WHERE email = ?'); $stmt->execute([$identifier]); $userData = $stmt->fetch(\PDO::FETCH_ASSOC); if (!$userData) { throw new UserNotFoundException(); } $user = new User(); $user->setId($userData['id']); $user->setEmail($userData['email']); $user->setPassword($userData['password']); $user->setName($userData['name']); $user->setRoles(json_decode($userData['roles'], true) ?? []); return $user; } }
3. 配置安全组件
修改config/packages/security.yaml配置,指定使用你自定义的用户提供器:
security: password_hashers: App\Entity\User: algorithm: auto providers: app_user_provider: id: App\Security\CustomUserProvider firewalls: main: lazy: true provider: app_user_provider # 如果你用表单登录,直接开启内置的form_login即可 form_login: login_path: app_login check_path: app_login username_parameter: email password_parameter: password logout: path: app_logout access_control: # 按你项目需求配置权限规则即可 - { path: ^/login, roles: PUBLIC_ACCESS } - { path: ^/, roles: ROLE_USER }
4. 实现登录控制器
登录控制器逻辑和官方示例完全一致,不需要做特殊修改:
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; class LoginController extends AbstractController { #[Route('/login', name: 'app_login')] public function index(AuthenticationUtils $authenticationUtils): Response { $error = $authenticationUtils->getLastAuthenticationError(); $lastUsername = $authenticationUtils->getLastUsername(); return $this->render('login/index.html.twig', [ 'last_username' => $lastUsername, 'error' => $error, ]); } #[Route('/logout', name: 'app_logout')] public function logout() { // 不需要写任何逻辑,Symfony会自动处理 } }
注意事项
- 如果你需要自定义登录逻辑(比如加验证码、登录成功后特殊跳转逻辑),可以自行实现
AbstractLoginFormAuthenticator子类,配置到firewall的custom_authenticators节点下即可,不需要修改用户提供器的逻辑 - 所有数据库操作都可以替换为你项目现有封装的数据库操作类,不需要强制使用PDO
- 密码哈希校验、会话保持等逻辑Symfony安全组件会自动处理,不需要额外开发
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

