所有文章 > 日积月累 > 使用Auth0构建和保护一个简单的Symfony API服务器
使用Auth0构建和保护一个简单的Symfony API服务器

使用Auth0构建和保护一个简单的Symfony API服务器

在这篇文章中,您将从零开始学习如何构建 Symfony API 服务器,并进一步了解如何保护某些端点。同时,您将会使用 Auth0 来处理身份验证与授权的相关事宜。本教程的完整源代码可以在 GitHub 上找到。

先决条件

要学习本教程,您应该具备 PHP 面向对象编程的合理知识以及使用 Symfony 构建应用程序的基本知识。您还需要以下内容:

  • Composer全局安装在您的计算机上以管理依赖项
  • Symfony CLI安装在您的计算机上。
  • Auth0 帐户。
  • Angular CLI全局安装在您的计算机上。请注意,您无需精通使用Angular来构建应用程序,因为在这里,您只需要测试我们将要构建的API即可。

你将构建什么

您将构建一个具有三个不同端点的简单 Symfony API 服务器。每个端点将根据用户拥有的访问权限返回不同类型的消息。

公共端点

  • GET /api/messages/public

这个端点应当可以被任何未经授权的人访问。预计会返回以下消息:

{
"message": "The API doesn't require an access token to share this message."
}

受保护端点

  • GET /api/messages/protected

该端点将受到保护,防止未经授权的访问。只有携带有效访问令牌并在HTTP请求标头中进行授权的用户,才能查看以下消息:

{
"message": "The API successfully validated your access token."
}

管理端点

  • GET /api/messages/admin

与受保护的端点相似,要访问这个端点,用户的访问令牌中需要包含访问管理数据的相应权限。这种机制通常被称为基于角色的访问控制(RBAC)。例如,要访问这个特定的端点,用户可能需要拥有read:admin-messages的权限。

入门

在这里,您将通过设置和安装新的 Symfony 应用程序及其所需的依赖项来开始构建 Symfony API。

搭建 Symfony 应用程序的脚手架

首先,打开终端,导航到您的首选开发目录,然后发出以下命令以使用Composer创建新项目:

composer create-project symfony/website-skeleton api-symfony-server

安装过程完成后,切换到刚刚创建的新目录:

cd api-symfony-server

```bash
cp .env .env.local

在 Symfony 项目中,.gitignore 文件配置了 Git 忽略的文件模式。该文件的好处之一是它有助于将您的凭据存储在代码之外以确保它们的安全。

接下来,更新DATABASE_URL参数,以便应用程序使用 SQLite 数据库而不是默认的 PostgreSQL。为此,请将现有条目注释掉,并取消注释 SQLite 选项,使其与下面的示例保持一致。

DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"

注意:数据库将在项目根目录的 var 目录中创建,并命名为.data.db

运行应用程序

确保您位于主项目目录中并使用Symfony CLI,使用以下命令启动应用程序:

symfony serve

导航到http://localhost:8000查看新 Symfony 应用程序的默认主页:

交响乐团主页

构建 API

在本节中,我们将首先处理公共端点,然后逐步着手处理其他端点,重点关注创建控制器以处理前面提到的每个端点的逻辑。

使用停止应用程序运行,然后点击CTRL + CEnter

创建控制器并配置每个端点

首先从项目根目录中的终端发出以下命令来创建控制器:

php bin/console make:controller APIController

您将看到以下输出:

 created: src/Controller/APIController.php
created: templates/api/index.html.twig

Success!

Next: Open your new controller class and add some pages!

找到新创建的控制器并使用以下src/Controller/APIController.php内容更新其内容:

// src/Controller/APIController.php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
* @Route("/api/messages")
*/
class APIController extends AbstractController
{
/**
* @Route("/public", name="public")
*/
public function publicAction()
: JsonResponse
{
return $this->json(["message" => "The API doesn't require an access token to share this message."], Response::HTTP_OK);
}

/**
* @Route("/protected", name="protected")
*/
public function protectedAction()
: JsonResponse
{
return $this->json(["message" => "The API successfully validated your access token."], Response::HTTP_OK);
}

/**
* @Route("/admin", name="admin")
*/
public function adminAction(): JsonResponse
{
return $this->json(["message" => "The API successfully recognized you as an admin."], Response::HTTP_OK);
}
}

从上面的代码片段来看,该控制器包含三种不同的方法:

  • publicAction()
  • protectedAction()
  • adminAction()

每个都被设计为处理不同的端点,并分别针对/public、/protected、/admin等端点返回适当的消息。

返回终端,再次启动应用程序symfony serve并打开 API 测试工具(例如Postman)来测试每个端点。

从公共端点开始。创建一个新的 GET 请求到此端点http://localhost:8000/api/messages/public。您将收到消息,如下图所示:

使用 Postman 的公共端点

接下来,尝试在 http://localhost:8000/api/messages/protected 上访问受保护的端点。

使用 Postman 保护端点

最后,[ http://localhost:8000/api/messages/admin ] ( http://localhost:8000/api/messages/admin )上的管理端点将为您提供消息:

使用 Postman 管理端点

目前,所有人都可以访问所有已创建的端点。然而,这显然不是我们想要的结果。您需要确保这些端点仅对授权用户开放。您将在下一节中开始配置。

如果您还没有的话,请务必立即注册一个免费的 Auth0 帐户。

保护受保护端点和管理端点的安全

您将使用 Auth0 来保护端点(受保护和管理)。为此,您需要返回Auth0 仪表板并配置 API。

首先,单击“应用程序”>“API”导航至Auth0 管理仪表板的 API 部分。如果您之前创建过任何 API,这将显示您帐户的所有 API 列表,但对于本教程,请继续单击“创建 API”按钮并设置一个新 API。

创建新的API

提供一个友好的名称(例如API)并将其标识符设置为Symfony API Serverhttps://localhost:8000RS256。您可以自由使用任何名称和标识符,但如果您想严格遵循本教程,则应保留上述值。将签名算法保持原样,并单击“创建”按钮继续。在本教程的后续部分中,您将需要用到此处生成的值。

安装依赖项并配置身份验证

为了保护 /api/messages/protected 和 /api/messages/admin 这两个 GET 端点,您将使用名为 auth0/jwt-auth-bundle 的 Symfony JWT 身份验证包。

使用以下命令停止应用程序运行,并运行以下命令以使用 Composer 安装捆绑包:

composer require auth0/jwt-auth-bundle:"~4.0"

在项目中安装完捆绑包后,您应该会在 config/packages/ 目录下找到 jwt_auth.yaml 文件。如果没有,请创建该文件并将以下内容粘贴到其中:

jwt_auth:
domain: "%env(AUTH0_DOMAIN)%"
client_id: "%env(AUTH0_CLIENT_ID)%"
audience: "%env(AUTH0_AUDIENCE)%"

之前,当您创建 API 时,Auth0 还会自动为您的 API 创建一个测试应用程序。这将是保存您的用户的 Auth0 应用程序。您可以通过单击“Applications”来找到它,然后从列表中选择与您的API命名相匹配的测试应用程序。如果您的名称与本教程中的名称相同,则它将是“Symfony API Server(测试应用程序)”。您还可以为您的帐户选择和使用任何其他应用程序。但对于本教程,单击测试应用程序,您将看到如下所示的页面:

测试应用

打开.env.local文件并更新以下环境变量的值:

CLIENT_ORIGIN_URL=http://localhost:4040
AUTH0_AUDIENCE=http://localhost:8000
AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_CLIENT_ID=YOUR_AUTH0_ID
AUTH0_CLIENT_SECRET=YOUR_AUTH0_CLIENT_SECRET

请确保将 YOUR_AUTH0_DOMAINYOUR_AUTH0_CLIENT_ID 和 YOUR_AUTH0_CLIENT_SECRET 这几个占位符替换成从 Auth0 仪表板上获取的实际值。

设置用户和用户提供者

处理身份验证和授权需要 Auth0 了解当前经过身份验证的用户。这是 Symfony 中用户提供程序的工作,因为它有助于从会话中重新加载用户,并加载用户以使用其他特定功能,例如使用用户名或电子邮件进行身份验证。

如果我们的 API 用户数据是存储在数据库中的,那么可能就不需要创建自定义的用户提供程序。但在这个场景下,我们需要从自定义的位置(即 Auth0)加载用户,因此必须创建一个自定义的用户提供程序。

首先,导航到该src文件夹​​并创建一个名为 的新文件夹Security,并在新创建的文件夹中创建另一个文件夹并将其命名为User。接下来,在文件夹中创建用户类User并将其命名为WebServiceUser.php.打开新创建的文件并将以下代码粘贴到其中:

<?php

namespace App\Security\User;

use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class WebServiceUser implements
UserInterface, EquatableInterface {

private $roles;
private $jwt;

public function __construct($jwt, $roles) {

$this->roles = $roles;
$this->jwt = $jwt;
}

/**
* @inheritDoc
*/
public function getRoles()
: array {

return $this->roles;
}

/**
* @inheritDoc
*/
public function getPassword()
: ?string {

return null;
}

/**
* @inheritDoc
*/
public function getSalt()
: ?string {

return null;
}

public function isEqualTo(UserInterface $user)
: bool {

if (!$user instanceof WebServiceUser) {
return false;
}

return $this->getUsername() === $user->getUsername();
}

/**
* @inheritDoc
*/
public function getUsername() {

return $this->jwt["email"] ?? $this->jwt["sub"];
}

/**
* @inheritDoc
*/
public function eraseCredentials() {
}

public function getUserIdentifier() {
return $this->jwt["email"] ?? $this->jwt["sub"];
}
}

这里,WebServiceUser该类实现了两个不同的接口:

  • UserInterface — 表示所有 User 类必须实现的接口
  • EquatableInterface — 用于测试两个对象在安全和重新身份验证上下文中是否相等

接下来,在文件夹中创建一个文件User并将其命名为WebServiceAnonymousUser.php.这将返回匿名用户。使用以下内容:

<?php

namespace App\Security\User;

class WebServiceAnonymousUser extends WebServiceUser {

public function __construct() {

parent::__construct(null, ['IS_AUTHENTICATED_ANONYMOUSLY']);
}

public function getUsername() {

return null;
}
}

最后,在User文件夹中创建另一个文件并将其命名为Web Service User Provider.php.完成后,将以下代码粘贴到其中:

<?php

namespace App\Security\User;

use Auth0\JWTAuthBundle\Security\Core\JWTUserProviderInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Polyfill\Intl\Icu\Exception\NotImplementedException;


class WebServiceUserProvider implements JWTUserProviderInterface {

public function loadUserByJWT($jwt)
: WebServiceUser {
$data = ['sub' => $jwt->sub];
$roles = [];
$roles[] = 'ROLE_OAUTH_AUTHENTICATED';

return new WebServiceUser($data, $roles);
}

public function getAnonymousUser()
: WebServiceAnonymousUser {

return new WebServiceAnonymousUser();
}

public function loadUserByUsername($username) {

throw new NotImplementedException('method not implemented');
}

public function refreshUser(UserInterface $user) {

if (!$user instanceof WebServiceUser) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($user))
);
}

return $this->loadUserByUsername($user->getUsername());
}

public function supportsClass($class)
: bool {

return $class === 'App\Security\User\WebServiceUser';
}

public function loadUserByIdentifier(string $identifier)
{
throw new NotImplementedException('method not implemented');
}
}

该类实现了之前安装的 Auth0 包中的 JWTUserProviderInterface,该接口指定了该类必须实现的重要方法。这些方法是作为 WebServiceUserProvider 的一部分来定义的。

  • loadUserByJWT:它接收解码后的 JWT 访问令牌并返回用户。
  • getAnonymousUser:返回代表未经身份验证的匿名用户(通常由角色表示IS_AUTHENTICATED_ANONYMOUSLY

创建 Guard 验证器

接下来,我们需要在 Symfony 中创建一个防护验证器。为此,请在文件夹中创建一个新文件并将其命名为src/Security/UserGuardAuthenticator.php.打开新文件并使用以下内容:

<?php


namespace App\Security\User;


use Auth0\JWTAuthBundle\Security\Guard\JwtGuardAuthenticator;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;

class GuardAuthenticator extends JwtGuardAuthenticator
{
public function start(Request $request, AuthenticationException $authException = null)
{
$responseBody = [
'message' => 'No authorization token was found',
];

return new JsonResponse($responseBody, JsonResponse::HTTP_UNAUTHORIZED);
}
}

这从包中扩展了 GuardAuthenticator 类,名为 JwtGuardAuthenticator,并检查 HTTP 请求标头中是否存在访问令牌。如果没有找到访问令牌,它会返回一条适当的消息。

配置安全提供者

在配置安全提供程序之前,为 WebServiceUserProvider 创建一个服务是一个好习惯,这可以使您的应用程序更易于维护和适应未来的新要求。您可以通过将此代码添加到文件底部来创建一个:

parameters:

services:
...
# 👇 new code starts here
web_service_user_provider:
class: App\Security\User\WebServiceUserProvider
arguments: ["@jwt_auth.auth0_service"]

最后,修改file中的文件security.yamlconfig/packages/security.yaml,使其包含以下内容:

  • 服务web_service_user_provider
  • 您想要使用访问令牌进行身份验证的安全区域
  • access_control包含每个路由所需角色的部分您可以将其完全替换为以下内容:
security:
enable_authenticator_manager: true

# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# users_in_memory: { memory: null }
web_service_user_provider:
id: App\Security\User\WebServiceUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/api
stateless: true
guard:
authenticators:
id: App\Security\User\GuardAuthenticator
provider: web_service_user_provider
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/api/messages/public, roles: PUBLIC_ACCESS }
- { path: ^/api/messages/protected, roles: ROLE_OAUTH_AUTHENTICATED }
- { path: ^/api/messages/admin, roles: ROLE_OAUTH_AUTHENTICATED }

现在,您可以通过访问受保护的路由,使用 Postman 再次测试这一点。通过运行symfony serve并访问来启动应用程序。您将收到一条消息,指示“未找到授权令牌”,如下所示:

未找到令牌

这是因为您需要提供一个有效的访问令牌,才能从 /protected 端点成功检索内容。

获取token并授权测试应用

动态生成访问令牌通常需要您的客户端应用程序获得 Auth0 的授权。但作为一个概念验证的示例,目前您可以从 Auth0 仪表板上直接获取并使用一个用于测试的令牌。为此,请导航至Auth0 仪表板中的 API 部分,然后单击您之前创建的 API。接下来,单击“Test”选项卡,并向下滚动到“响应”部分,在“access_token”副标题下复制显示的内容。

再次打开 Postman,在“授权”选项卡中选择“Bearer Token”,然后粘贴您的访问令牌。

不记名令牌

现在您可以尝试受保护的端点,您将收到消息,如下所示:

受保护端点响应

为 API 实施基于角色的访问控制

正如之前提到的,/api/messages/admin 端点需要访问令牌来授予访问管理数据的权限。这通常被称为基于角色的访问控制 (RBAC),在这种机制中,用户的权限是根据他们在组织中所担任的角色来分配的。对于 GET /api/messages/admin,需要分配 read:admin-messages 权限。

在本节中,要实施和配置此访问控制,您将执行以下操作:

  • 在 Auth0 仪表板中启用 RBAC(基于角色的访问控制)设置
  • admin在仪表板中创建角色
  • 创建特定的权限,即 read:admin-messages
  • 将新创建的权限添加到admin角色中。
  • 将新角色分配给特定用户

启用 RBAC 设置

为了使基于角色的访问控制 (RBAC) 正常运作,您必须通过仪表板或管理 API 为您的 API 启用该功能。

导航到 Auth0 仪表板并单击 API,然后选择之前创建的 API ,然后向下滚动到RBAC 设置部分:

角色访问控制设置

通过切换此处的两个按钮来启用 RBAC:“启用 RBAC”和“在访问令牌中添加权限”。这将为任何选择的端点实施基于角色的访问控制授权策略,并确保将声明permissions添加到访问令牌中。单击“保存”按钮以更新更改。

创建管理员角色

您既可以通过 Auth0 的仪表板,也可以通过其管理 API 来创建角色。这些角色能够与 Auth0 的 API 授权核心功能集一起使用。

转到以下内容:

  • 仪表板
  • 单击侧面菜单栏中的“用户管理”
  • 单击角色
  • 接下来,单击创建角色按钮

给角色起一个名字,比如“管理员”,并为其添加描述,例如“读取所有管理消息”。

创建新角色

创建权限

从仪表板中的 API 菜单返回该页面,然后单击同一页面中的“权限”选项卡来定义权限及其范围。

在“权限(范围)”下方,输入 read:admin-messages。对于“说明”字段,请输入“读取管理消息”。确保单击“添加”按钮以保存该权限。

创建权限

为角色添加权限

现在您已经创建了Admin角色及其对应的权限,接下来要做的就是为新创建的角色添加权限。

返回“用户管理”>“角色”中的“角色”页面。

角色列表

单击您之前创建的管理员角色,然后单击“权限”选项卡。现在单击添加权限按钮。你会看到这样的页面:

添加权限

从列表中选择您的 API;在我们的例子中,应选择“Symfony API Server”,并为它分配 read:admin-messages 权限。选中旁边的框以指示管理员角色的权限。最后,单击“添加权限”以保存更改。

为用户分配角色

有两种方法可以为用户分配角色。您可以从“用户”列表中选择用户,然后分配角色,也可以转至单个用户的“用户详细信息”(用户配置文件)页面,然后在“角色”选项卡中选择要分配的角色。您将坚持使用本教程中的用户列表。

为此:

  1. 转到仪表板 > 用户管理 > 用户。
  2. 单击要修改的用户旁边的“ … ”,然后选择分配角色
  3. 选择您要分配的角色,然后单击“分配”
为用户分配角色

更新Web服务用户提供者

此时,一旦用户通过 API 进行身份验证,返回的 access token 信息中将包含用户所拥有的权限。具体来说,如果用户具有 权限,则该信息中会包含这一项;否则,则不包含。要在允许用户访问管理数据之前检查此权限,您将更新read:admin-messagessrc/Security/User/WebServiceUserProvider.php文件,如下所示:

...
class WebServiceUserProvider implements JWTUserProviderInterface {

public function loadUserByJWT($jwt)
: WebServiceUser {
$data = ['sub' => $jwt->sub];
$roles = [];
$roles[] = in_array('read:admin-messages', $jwt->permissions) ? 'ROLE_ADMIN' : 'ROLE_OAUTH_AUTHENTICATED';

return new WebServiceUser($data, $roles);
}
...
}

在这里,您会检查权限数组中是否存在 read:admin-messages。如果存在,那么会将 ROLE_ADMIN 角色分配给经过身份验证的用户;如果不存在,则会分配一个基本的 ROLE_OAUTH_AUTHENTICATED 角色。

另外,请打开 config/packages/security.yaml 文件并更新其内容,如下所示:

security:
enable_authenticator_manager: true

# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# users_in_memory: { memory: null }
web_service_user_provider:
id: App\Security\User\WebServiceUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/api
stateless: true
guard:
authenticators:
id: App\Security\User\GuardAuthenticator
provider: web_service_user_provider
role_hierarchy:
ROLE_ADMIN: [ROLE_OAUTH_AUTHENTICATED, ROLE_ALLOWED_TO_SWITCH]
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/api/messages/public, roles: PUBLIC_ACCESS }
- { path: ^/api/messages/protected, roles: ROLE_OAUTH_AUTHENTICATED }
- { path: ^/api/messages/admin, roles: ROLE_ADMIN }

从上面的代码片段中,您更新了api/messages/admin端点的角色。

创建事件订阅者

一旦未经授权的用户在没有适当权限的情况下尝试访问任何端点,就会抛出异常,表明此类访问被禁止。

在本部分中,您将创建一个事件订阅者,它将侦听禁止的事件并返回适当的消息。为此,请在 src 目录中创建一个命名文件夹(如果还没有的话),然后在这个文件夹中创建一个名为 ExceptionSubscriber.php 的新文件。接下来,打开这个新创建的文件,并使用以下内容填充它:

<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

class ExceptionSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
KernelEvents::EXCEPTION => ['onKernelException']
];
}

public function onKernelException(ExceptionEvent $event)
{
$exception = $event->getThrowable();
if ($exception instanceof AccessDeniedHttpException) {
$event->setResponse(new JsonResponse([
'message' => "Insufficient scopes.",
], Response::HTTP_UNAUTHORIZED));
$event->stopPropagation();
}
return $exception;
}
}

完成所有必需的更改后,通过发出以下命令来运行 API 服务器:

symfony serve

测试管理端点

正如之前提到的,与迄今为止所创建的其他端点不同,这个 /api/messages/admin 端点要求访问令牌中必须包含特定的权限(read:admin-messages)。由于通过 Auth0 仪表板来操作来自机器对机器应用程序的访问令牌既有些困难又不被推荐,因此我们将采取一种不同的方法,即使用客户端应用程序来模拟和测试客户端与服务器之间的交互。

目前,这是确保我们有一个界面供用户执行以下操作的最佳方式:

  • 登录和注销
  • 检索用户个人资料信息
  • 保护应用路径
  • 安全调用 API

注意:在此过程中,如果您有自己的客户端应用程序,请随意使用它来进行测试。

要使用预构建的客户端应用程序,请从终端发出以下命令以从 GitHub 克隆应用程序:

git clone https://github.com/auth0-sample-gallery/spa_angular_typescript_hello-world.git hello-world-demo

这会将演示应用程序克隆到开发目录中命名hello-world-demo的新文件夹中。

在安装项目的依赖项之前,请确保您的系统上已经安装了 Angular CLI。您可以通过在终端中运行相应的命令来验证这一点。

ng --version

输出将是您系统上安装的 Angular CLI 当前版本的详细信息。如果未安装,请按照此处的说明全局配置 Angular CLI。

进入新项目的文件夹并发出以下命令来安装所需的依赖项:

// Change directory
cd hello-world-demo

// Install dependencies
npm install

起始项目使用自定义样式表来设计应用程序的样式和布局,因此您无需进行任何更改。

将客户端应用程序连接到 Auth0

接下来,您需要将此应用程序连接到 Auth0。返回 Auth0 仪表板,单击“应用程序”>“应用程序”>“创建应用程序”。

为其命名为“Angular Symfony App”,然后选择“单页 Web 应用程序”作为应用程序名称。最后,点击“创建”。

授权0

每当发出身份验证请求时,Angular 演示应用程序都会将用户重定向到 Auth0 的登录页面。之后,Auth0 会使用必要的凭据将用户重定向回应用程序。

为了安全地进行重定向,您必须指定 Auth0 在验证用户凭据后可以重定向到的 URL。返回Auth0 仪表板,选择为您的 API 创建的应用程序,单击该页面上的“设置”选项卡,然后向下滚动以找到以下字段:

  • 允许的回调 URL
  • 允许的 Web 来源
  • 允许的注销 URL

用作每个字段的值,因为在开发过程中可以通过该 URL 访问客户端应用程序。单击“保存更改”继续。

在正确指定了 URL 之后,您需要将客户端应用程序与 Auth0 连接起来。这可以通过在客户端应用程序的根目录中创建一个名为 env.json 的新文件,并按照以下方式填充该文件来实现:

{
"domain": "YOUR_AUTH0_DOMAIN",
"clientId": "YOUR_AUTH0_CLIENT_ID",
"audience": "http://localhost:8000",
"apiServerUrl": "http://localhost:8000"
}

确保使用Auth0 仪表板中应用程序页面中的值填写“域”和“客户端 ID” 。现在,继续使用以下命令运行应用程序:

ng serve

导航到http://localhost:4040以访问该应用程序。

Angular 演示应用程序页面

启用客户端应用程序和 Symfony API 服务器之间的通信

默认情况下,为保障安全,浏览器会禁止不同域的应用程序之间交互和共享资源,除非得到应用程序的明确允许。这意味着目前将禁用从客户端应用程序向 Symfony API 发送 HTTP 请求。要启用两个应用程序之间的通信,您需要启用CORS(跨源资源共享)。

要启用 Symfony API,您需要使用Nelmo Bundle。运行以下命令来安装它:

composer require nelmio/cors-bundle

安装过程完成后,将在文件夹中生成一个名为nelmio_cors.yamlconfig/packages的默认配置文件,如下所示:

nelmio_cors:
defaults:
origin_regex: true
allow_origin: ["%env(CORS_ALLOW_ORIGIN)%"]
allow_methods: ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]
allow_headers: ["Content-Type", "Authorization"]
expose_headers: ["Link"]
max_age: 3600
paths:
"^/": null

此处所指定的默认配置通常已经足够,因为它涵盖了所有适当的 HTTP 动词。接下来,请导航到该文件并更新其内容,具体更新如下:

####> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
####< nelmio/cors-bundle ###

在这里,我们指定应允许 localhost URL。

最后,启动 Symfony 服务器:

    symfony serve

在客户端应用程序中,单击外部 API按钮并提供您的凭据。

确保您使用具有 Auth0 仪表板上指定的管理员角色的用户详细信息进行登录。

查看管理端点响应

您还可以通过单击端点的“公共”按钮或端点的“受保护”按钮来检查其他端点,分别如下所示:

查看公共端点响应
查看受保护端点响应

结论

通过本教程,您已经学习了如何轻松地构建一个 Symfony API 服务器。这个服务器包含了一些无需身份验证即可由互联网上的任何人访问的端点,同时也包含了一些需要适当授权和角色才能访问的其他端点。

您通过从公共端点开始并进一步创建两个受保护端点(即私有端点和管理端点)来连续创建这些端点。为了完全设置和配置受保护端点的身份验证与授权,您利用了 Auth0 的 API。这样,只有那些 HTTP 请求在授权标头中包含了有效的访问令牌,才能够成功地检索数据。

我希望本教程对您有所帮助。本文中构建的 API 服务器的完整源代码可以在 GitHub 上找到。

原文链接:https://auth0.com/blog/build-and-secure-a-simple-symfony-api-server-using-auth0/

#你可能也喜欢这些API文章!