
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息,通常用于身份验证和信息交换。在API开发中,JWT常用于实现无状态认证:用户登录成功后,服务器返回一个JWT,客户端在后续请求中将此JWT放入HTTP Authorization 头(通常以Bearer前缀),服务器通过验证JWT来识别用户身份并授权访问。
在Symfony中实现JWT认证,通常涉及以下几个核心组件:
security.yaml是Symfony安全组件的核心配置文件,它定义了认证提供者、密码哈希器、防火墙以及访问控制规则。
以下是一个典型的security.yaml配置片段,用于支持JWT认证:
security:
enable_authenticator_manager: true # 启用新的认证管理器 (Symfony 5.3+)
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
providers:
# 这里可以使用in_memory,但在实际应用中通常是Doctrine实体用户提供者
users_in_memory: { memory: null }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false # 开发工具和静态资源不进行安全检查
main:
guard:
authenticators:
- App\Security\JwtAuthenticator # 指定自定义的JWT认证器
lazy: true # 懒加载认证器
provider: users_in_memory # 指定用户提供者
stateless: true # 声明此防火墙是无状态的,不使用session配置解析:
JwtAuthenticator是实现JWT验证逻辑的核心类。它继承自AbstractGuardAuthenticator(或实现AuthenticatorInterface)。
namespace App\Security;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Firebase\JWT\JWT;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
class JwtAuthenticator extends AbstractGuardAuthenticator
{
private $em;
private $params;
public function __construct(EntityManagerInterface $em, ContainerBagInterface $params)
{
$this->em = $em;
$this->params = $params;
}
/**
* 当认证失败,且未提供凭据时调用。例如,请求未包含Authorization头。
*/
public function start(Request $request, AuthenticationException $authException = null): JsonResponse
{
return new JsonResponse(['message' => 'Authentication Required'], Response::HTTP_UNAUTHORIZED);
}
/**
* 判断当前请求是否需要此认证器处理。
* 如果请求头中包含'Authorization',则返回true。
*/
public function supports(Request $request): bool
{
return $request->headers->has('Authorization');
}
/**
* 从请求中提取认证凭据(即JWT)。
*/
public function getCredentials(Request $request)
{
return $request->headers->get('Authorization');
}
/**
* 根据凭据加载用户。
* 在这里,我们解码JWT,并根据其中的'sub'(主题)字段从数据库中查找用户。
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
try {
// 移除'Bearer '前缀
$token = str_replace('Bearer ', '', $credentials);
// 解码JWT,需要提供密钥和算法
$jwtData = (array) JWT::decode($token, $this->params->get('jwt_secret'), ['HS256']);
// 从数据库中查找用户,假设'sub'字段存储用户ID
// 注意:App:ATblUsers 是一个简化写法,实际应使用完整的实体类名
return $this->em->getRepository('App\Entity\ATblUsers')->find($jwtData['sub']);
} catch (\Exception $exception) {
// JWT解码失败(如过期、签名无效)则抛出认证异常
throw new AuthenticationException($exception->getMessage());
}
}
/**
* 检查凭据是否有效。
* 对于JWT,通常在getUser方法中完成所有验证,此方法可以为空。
*/
public function checkCredentials($credentials, UserInterface $user)
{
// JWT的验证通常在getUser中完成,这里可以留空或进行额外检查
return true;
}
/**
* 认证失败时调用。
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): JsonResponse
{
return new JsonResponse([
'message' => $exception->getMessage()
], Response::HTTP_UNAUTHORIZED);
}
/**
* 认证成功时调用。
* 对于无状态API,通常无需做任何操作。
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
{
return; // 返回null或空,表示继续处理请求
}
/**
* 是否支持“记住我”功能。对于无状态API,通常返回false。
*/
public function supportsRememberMe(): bool
{
return false;
}
}方法解析:
尽管防火墙和认证器都已配置,但如果API端点仍然可以未经认证访问,那很可能是因为security.yaml中的access_control规则配置不当或缺失。access_control是Symfony安全组件中用于定义URL路径与所需角色之间映射关系的关键部分。它按顺序匹配URL路径,并应用第一个匹配的规则。
原配置中缺少了对根路径/的访问控制,导致所有路径都可以被未认证用户访问。
为了确保除了认证登录接口外,所有其他API接口都必须经过JWT认证,我们需要在security.yaml中添加或修改access_control部分:
security:
# ... (其他配置保持不变)
access_control:
# 允许所有用户访问 /authenticate 路径(登录接口)
- { path: ^/authenticate, roles: PUBLIC_ACCESS }
# 要求所有其他路径都必须完全认证 (IS_AUTHENTICATED_FULLY)
- { path: ^/, roles: IS_AUTHENTICATED_FULLY }配置解析:
重要提示: access_control规则的顺序至关重要。Symfony会从上到下依次匹配规则,一旦找到匹配项,就会应用该规则并停止。因此,更具体的规则(如/authenticate)应放在更宽泛的规则(如/)之前。
parameters:
jwt_secret: '%env(JWT_SECRET)%'然后在.env文件中设置JWT_SECRET。
通过本教程,您应该了解了如何在Symfony 5.3中正确配置和实现基于JWT的API认证。核心在于:
遵循这些步骤和最佳实践,您将能够构建一个安全、高效的无状态API认证系统。
以上就是在Symfony 5.3中实现JWT令牌验证与访问控制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号