API Platform集成Keycloak/OAuth2身份认证求助
API Platform集成Keycloak身份认证全攻略
嘿,作为同样踩过API Platform+Keycloak坑的开发者,我来给你拆解两种可行的方案,帮你搞定认证问题!
方案一:用API Platform自带的OAuth2配置
你看到的oauth配置项确实是API Platform自带的,但它需要和Symfony的Security配置配合才能生效——光单独配置API Platform是没用的,这也是你之前请求还返回200的核心原因。
1. 配置API Platform的OAuth参数
打开config/packages/api_platform.yaml,在api_platform节点下添加security配置,把Keycloak的客户端信息填进去:
api_platform: # 其他配置... security: oauth: client_id: '%env(KEYCLOAK_CLIENT_ID)%' client_secret: '%env(KEYCLOAK_CLIENT_SECRET)%' token_uri: '%env(KEYCLOAK_BASE_URL)%/realms/%env(KEYCLOAK_REALM)%/protocol/openid-connect/token' authorization_uri: '%env(KEYCLOAK_BASE_URL)%/realms/%env(KEYCLOAK_REALM)%/protocol/openid-connect/auth' redirect_uri: '%env(APP_URL)%/oauth/callback' # 授权码模式需配置 scopes: ['openid', 'profile', 'email']
记得在.env文件里配置对应的环境变量:
KEYCLOAK_BASE_URL=https://your-keycloak-domain KEYCLOAK_REALM=your-realm-name KEYCLOAK_CLIENT_ID=your-api-client-id KEYCLOAK_CLIENT_SECRET=your-api-client-secret
2. 配置Symfony Security防火墙
打开config/packages/security.yaml,设置API路径的防火墙,启用OAuth2守卫,并配置用户信息获取逻辑:
security: # 其他配置... firewalls: # 其他防火墙... api: pattern: ^/api stateless: true oauth2: authorization_url: '%env(KEYCLOAK_BASE_URL)%/realms/%env(KEYCLOAK_REALM)%/protocol/openid-connect/auth' token_url: '%env(KEYCLOAK_BASE_URL)%/realms/%env(KEYCLOAK_REALM)%/protocol/openid-connect/token' client_id: '%env(KEYCLOAK_CLIENT_ID)%' client_secret: '%env(KEYCLOAK_CLIENT_SECRET)%' user_provider: app_user_provider # 自定义用户提供者 # JWT验证配置(可选) jwt: jwks_url: '%env(KEYCLOAK_BASE_URL)%/realms/%env(KEYCLOAK_REALM)%/protocol/openid-connect/certs' access_control: - { path: ^/api, roles: ROLE_USER } # 无认证请求将返回403
3. 关键坑点提醒
- 确保Keycloak客户端的访问类型设置为
confidential(使用客户端密钥时必须) - 前后端分离的API推荐用
client_credentials模式,或让前端获取JWT后传给API - 请求返回200大概率是
access_control未配置,或防火墙未匹配/api路径
方案二:使用oauth2-keycloak扩展
这个扩展封装了Keycloak特有的OAuth2逻辑,用起来更省心,适合新手快速上手。
1. 安装扩展
通过Composer安装依赖:
composer require stevenmaguire/oauth2-keycloak
2. 注册Keycloak客户端服务
打开config/services.yaml,定义Keycloak客户端服务:
services: # 其他服务... Stevenmaguire\OAuth2\Client\Provider\Keycloak: arguments: $options: authServerUrl: '%env(KEYCLOAK_BASE_URL)%' realm: '%env(KEYCLOAK_REALM)%' clientId: '%env(KEYCLOAK_CLIENT_ID)%' clientSecret: '%env(KEYCLOAK_CLIENT_SECRET)%' redirectUri: '%env(APP_URL)%/oauth/callback' $collaborators: []
3. 配置Symfony Security使用自定义客户端
回到config/packages/security.yaml,修改防火墙的oauth2配置,指定使用这个Keycloak客户端:
security: # 其他配置... firewalls: api: pattern: ^/api stateless: true oauth2: client: Stevenmaguire\OAuth2\Client\Provider\Keycloak user_provider: app_user_provider access_control: - { path: ^/api, roles: ROLE_USER }
4. 实现自定义用户提供者
需要创建一个类,把Keycloak返回的用户信息映射到Symfony的User实体:
// src/Security/UserProvider.php namespace App\Security; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UserNotFoundException; use App\Entity\User; class UserProvider implements UserProviderInterface { public function loadUserByIdentifier(string $identifier): UserInterface { // 根据Keycloak返回的用户名/邮箱,从数据库或内存中获取用户 $user = new User(); $user->setEmail($identifier); $user->setRoles(['ROLE_USER']); return $user; } public function refreshUser(UserInterface $user): UserInterface { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class)); } return $this->loadUserByIdentifier($user->getUserIdentifier()); } public function supportsClass(string $class): bool { return User::class === $class || is_subclass_of($class, User::class); } }
然后在services.yaml里注册这个服务:
services: App\Security\UserProvider: tags: ['security.user_provider']
最后再检查一遍:
- 所有环境变量配置正确
- Keycloak客户端的权限和授权类型匹配你的场景
- Symfony的Security防火墙和访问控制规则覆盖了API路径
这样配置完之后,未认证的请求访问API就会返回403了!
内容的提问来源于stack exchange,提问作者Matthieu Tartiere
相关产品推荐
相关产品推荐

