You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为API Platform接入外部OpenID提供商(Azure OAuth2)实现认证

在Symfony 6中为API Platform接入Azure OpenID OAuth2认证

以下是基于你现有JWT和API Platform配置的完整实现步骤:

1. 安装依赖

首先安装OAuth2客户端工具包和Azure提供商:

composer require knpuniversity/oauth2-client-bundle league/oauth2-azure

2. 配置Azure Active Directory应用

在Azure门户完成以下操作:

  • 创建应用注册,记录客户端ID、客户端密钥、租户ID
  • 设置重定向URI为https://你的后端域名/login/azure/check
  • 在应用的令牌配置中启用ID令牌(OpenID Connect必需)

3. 配置OAuth2客户端

编辑config/packages/knpu_oauth2_client.yaml:

knpu_oauth2_client:
    clients:
        azure:
            type: azure
            client_id: '%env(AZURE_CLIENT_ID)%'
            client_secret: '%env(AZURE_CLIENT_SECRET)%'
            tenant_id: '%env(AZURE_TENANT_ID)%'
            redirect_route: azure_check
            redirect_params: {}

在.env文件中添加环境变量:

AZURE_CLIENT_ID=你的Azure客户端ID
AZURE_CLIENT_SECRET=你的Azure客户端密钥
AZURE_TENANT_ID=你的Azure租户ID

4. 配置Security防火墙

修改config/packages/security.yaml,整合Azure OAuth2登录和JWT认证:

security:
    providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider
            oauth2_login:
                provider: azure
                login_path: /login/azure
                check_path: /login/azure/check
                success_handler: App\Security\AzureAuthenticationSuccessHandler
            logout:
                path: /logout
                target: /
        api:
            pattern: ^/api
            stateless: true
            jwt: ~
            entry_point: jwt
    access_control:
        - { path: ^/login/azure, roles: PUBLIC_ACCESS }
        - { path: ^/api, roles: ROLE_USER }

5. 创建认证成功处理器

这个类负责将Azure用户关联到本地用户,并生成JWT返回给前端:

<?php

namespace App\Security;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;

class AzureAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
    public function __construct(
        private EntityManagerInterface $em,
        private JWTTokenManagerInterface $jwtManager,
        private UserProviderInterface $userProvider
    ) {}

    public function onAuthenticationSuccess(Request $request, TokenInterface $token): JsonResponse
    {
        $azureUser = $token->getUser();
        $email = $azureUser->getEmail();

        // 查找本地用户,不存在则创建
        try {
            $user = $this->userProvider->loadUserByIdentifier($email);
        } catch (\Exception $e) {
            $user = new User();
            $user->setEmail($email);
            $user->setUsername($azureUser->getName());
            $user->setRoles(['ROLE_USER']);
            $this->em->persist($user);
            $this->em->flush();
        }

        // 生成JWT令牌
        $jwt = $this->jwtManager->create($user);

        return new JsonResponse([
            'token' => $jwt,
            'user' => [
                'id' => $user->getId(),
                'email' => $user->getEmail(),
                'roles' => $user->getRoles()
            ]
        ]);
    }
}

确保你的User实体实现了Symfony\Component\Security\Core\User\UserInterface,并包含email、username、roles等必要字段。

6. 添加路由

编辑config/routes.yaml,添加Azure登录和回调的路由:

azure_login:
    path: /login/azure
    methods: GET

azure_check:
    path: /login/azure/check
    methods: GET|POST

7. 配置API Platform权限

在你的API资源实体上添加安全注解,确保只有认证用户能访问:

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Security\Core\Annotation\IsGranted;

/**
 * @ApiResource(
 *     security="is_granted('ROLE_USER')",
 *     collectionOperations={"get", "post"},
 *     itemOperations={"get", "put", "delete"}
 * )
 * @IsGranted("ROLE_USER")
 */
class YourResource
{
    // 实体字段和方法
}

8. 前端React适配

  • 添加登录按钮,跳转到后端的Azure登录路由:
<button onClick={() => window.location.href = 'https://你的后端域名/login/azure'}>
    使用Azure登录
</button>
  • 登录成功后,后端返回包含JWT的JSON,前端将令牌存储到本地,后续请求API时携带:
// 示例:获取并存储令牌
fetch('https://你的后端域名/login/azure/check')
    .then(res => res.json())
    .then(data => {
        localStorage.setItem('jwt_token', data.token);
    });

// 示例:携带令牌请求API
fetch('https://你的后端域名/api/your-resources', {
    headers: {
        'Authorization': `Bearer ${localStorage.getItem('jwt_token')}`
    }
})

9. 测试验证

  1. 启动Symfony后端,确认环境变量配置正确
  2. 点击前端登录按钮,完成Azure账号登录
  3. 拿到JWT后,请求API Platform接口,验证是否能正常访问受保护资源

内容的提问来源于stack exchange,提问作者Amin Hoseiny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 09:35:21