您正在制作与游戏相关的应用吗?您是否要求用户进行身份验证?但最重要的是,您是游戏玩家(尽管这不是必需的)吗?
本教程是为您创建的!
OAUTH2协议
如果您已经熟悉OAuth2协议,则可以跳到下一部分。
我不会就oauth2协议以及它的出色表现进行任何革命性的演讲,所以起初,我要引用官方的oauth2.net网站:
oauth 2.0是授权的行业标准协议。 OAuth 2.0专注于客户开发人员的简单性,同时为Web应用程序,桌面应用程序,手机和客厅设备提供特定的授权流。
简单的单词,这意味着用户,作为客户端,只需单击按钮即可使用Google,Facebook,Discord等外部服务连接到您的应用程序,等等。
除了简化身份验证外,它还使注册方式更加容易,因为没有!
使用此协议,主要资源是访问令牌。这里的目标是使用您的秘密API密钥获得此访问令牌,并使用它来从提供商那里检索资源(例如用户数据)。
在这里,我已经释放了我的技能,并在油漆上画了一幅画画,因此您可以理解:
请注意,身份验证和资源服务器可以相同。
注册您的应用
第一步,但并非最不重要的一点是,进入Discord's developer portal以注册您的应用程序。完成此操作后,您将获得API键,使您能够将请求发送到Discord API。
â!在您继续之前,请确保您有一个仍然可用的Discord帐户。
找到按钮
首先,单击“新应用程序”按钮。您可以在您的个人资料旁边的门户网站的右上角找到它:
输入名称
完成此操作后,将会出现弹出窗口,以便您可以为应用程序命名。出于教程的目的,该应用将称为“ Oauthtutorial”:
显然,不要忘记阅读服务条款ð
您现在可以访问该应用程序的仪表板。
创建Symfony应用程序
在这一部分中,我们将在基本的Symfony项目设置中运行。如果您已经熟悉Symfony,则可以转到下一部分。
设置项目
打开一个终端和以下命令:
symfony new --webapp DiscordOauthTutorial
如果您还没有安装Symfony CLI,尽管我强烈建议您这样做,但请运行以下无聊命令:
composer create-project symfony/skeleton:"6.3.*" DiscordOauthTutorial
cd DiscordOauthTutorial
composer require webapp
运行网络服务器
您在您喜欢的IDE 中打开了该项目后,显然是php Storm,我的意思是其他,运行以下命令:
symfony server:start
您现在已经启动了本地Web服务器,该应用程序默认情况下在https://127.0.0.1:8000/上可用。如果单击该链接,您将受到Symfony Welcome Page的欢迎。
如果您遇到问题或希望了解有关本地Web服务器的更多信息,click here。
数据库内容
此部分适用于希望使用Symfony的身份验证系统对用户进行身份验证的人员。这需要使用User
实体创建数据库。如果您不想这样做(which is possible),请跳到下一部分。
首先,让我们在我们的.env
文件中修改数据库信息以匹配我们的数据库的设置:
DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
让我们假设我们正在使用Mariadb。
然后运行:
php bin/console doctrine:database:create
创建实体
现在我们的数据库还活着,运行以下命令:
php bin/console make:entity
出于教程的目的,我们将调用实体User
(normy)。
这里的主要目标是添加(例如)discordId
属性,该属性将是string
。这将保持用户的不和谐ID,因此您可以在身份验证时检索或创建它。
我们的实体应该看起来像这样:
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $discordId = null;
// getters and setters
}
迁移到数据库
现在,让我们利用学说的魔法将实体推入我们的数据库。为此,学说使用migrations。这些是SQL的行,描述了自上次迁移以来数据库中发生的变化。
显然,我们不必自己生成迁移,只需运行:
php bin/console make:migration
这将在我们项目的migrations
文件夹中生成一个文件。迁移名称为“版本”,后跟日期时间。
检查一下,推动它。
php bin/console doctrine:migrations:migrate
我们开始做吧
幸运的是,这个星球培养了制造伟大事物的伟大人物。我不知道KNP大学的人们是否很棒,但是据我所知,他们为帮助我们实施复杂的事情而制造了很棒的工具。因此,让我们使用以下工具之一,即KNP OAuth2 Client bundle。
安装捆绑包
要安装捆绑包,运行:
composer require knpuniversity/oauth2-client-bundle
作曲家下载了捆绑包后,它将询问您是否希望执行此捆绑包的食谱,应该。食谱将生成捆绑包的配置文件,可以在config/packages/knpu_oauth2_client.yaml
中找到。
如果由于某些原因没有发生,请创建文件并将其粘贴在其中:
knpu_oauth2_client:
clients:
# configure your clients as described here: https://github.com/knpuniversity/oauth2-client-bundle#configuration
安装Oauth Discord客户端
由于KNP软件包为OAuth身份验证提供了灵活的工具,因此您需要安装客户端才能工作。地球上另一个伟大的人已经做到了!因此,为了安装它,运行:
composer require wohali/oauth2-discord-new
More information about the client here
配置客户端
由于我们使用OAuth2对用户进行身份验证,因此我们需要API键。现场,您刚刚创建了一个Discord应用程序!让我们收集我们需要的东西!
首先,转到应用程序的仪表板,然后获取应用程序ID:
转到我们的.env.local
文件,然后将应用程序ID粘贴到一个全新的变量中,该变量将称为DISCORD_APP_ID
:
DISCORD_APP_ID=app_id
对于秘密钥匙,它总是更复杂...
单击屏幕左侧的侧边栏的“ OAuth2”部分,然后单击“常规”链接:
在此页面上,您应该找到以下内容:
单击此按钮,获取秘密键,紧紧握住它,然后将其粘贴到另一个变量中,该变量将称为DISCORD_SECRET_KEY
:
DISCORD_SECRET_KEY=app_secret
请注意,该应用程序的秘密密钥很重要且私密,不得泄漏。如果您在配置该项目时遇到问题,请不要发送屏幕截图,人们可以看到它。
现在我们的环境变量已经设置了,返回到yaml配置文件,然后像这样填充:
knpu_oauth2_client:
clients:
discord:
type: discord
client_id: '%env(DISCORD_APP_ID)%'
client_secret: '%env(DISCORD_SECRET_KEY)%'
redirect_route: auth_discord_login
您可以看到,我们有一个redirect_route
参数,该参数设置了尚不存在的路由名称。这条路线是用户身份验证的魔术的地方。
创建登录路线
让我们创建一个名为DiscordController
的Controller。我建议您不要使用maker command,因为它也会生成一个模板,我们不想要这个模板。
创建控制器后,创建了这样的路由:
namespace App\Controller;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
#[AsController]
#[Route("/auth/discord", name: "auth_discord_")]
final class DiscordController
{
#[Route("/login", name: "login")]
public function login(Request $request, ClientRegistry $clientRegistry)
{
}
}
这里的方法是空的,因为登录过程将由自定义身份验证器处理。但是,如果您愿意,您可以在其中add logic in order to check authentication。
为了使其清洁,我们将不和谐身份验证分为/auth/discord/
前缀。
-
/auth
零件要明确我们处于身份验证过程中。 -
/discord
零件将不和谐验证与您可以添加的任何身份验证分开。
现在,我们的应用知道了方式,也必须不和谐。因此,让我们回到开发人员门户网站,进入OAuth2>“常规页面”。
在此页面中,您将能够设置重定向URL 。提醒您,在OAuth2过程中,是在用户在供应商页面上进行身份验证后生成的代码的URL(用户必须说“是”才能访问其数据)。
)。所以让我们添加此URL:
创建身份验证器
为了管理身份验证,Symfony使用Authenticators。这些基本上是定义如何检索用户以及一旦完成工作的服务。
让我们现在创建大男孩:
<?php
namespace App\Security;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Wohali\OAuth2\Client\Provider\DiscordResourceOwner;
final class DiscordAuthenticator extends OAuth2Authenticator implements AuthenticationEntryPointInterface
{
public function __construct(
private readonly ClientRegistry $clientRegistry,
private readonly EntityManagerInterface $em,
private readonly RouterInterface $router,
private readonly UserRepository $userRepository
) {}
public function start(Request $request, AuthenticationException $authException = null): RedirectResponse
{
return new RedirectResponse($this->router->generate("auth_discord_start"), Response::HTTP_TEMPORARY_REDIRECT);
}
public function supports(Request $request): ?bool
{
return $request->attributes->get("_route") === "auth_discord_login";
}
public function authenticate(Request $request): SelfValidatingPassport
{
$client = $this->clientRegistry->getClient("discord");
$accessToken = $this->fetchAccessToken($client);
return new SelfValidatingPassport(
new UserBadge($accessToken->getToken(), function () use ($accessToken, $client) {
/** @var DiscordResourceOwner $discordUser */
$discordUser = $client->fetchUserFromToken($accessToken);
$user = $this->userRepository->findOneBy(["discordId" => $discordUser->getId()]);
if (null === $user) {
$user = new User();
$user->setDiscordId($discordUser->getId());
$this->em->persist($user);
}
$this->em->flush();
return $user;
})
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
// redirect to user to your post authentication page (e.g. dashboard, home)
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
// do something
}
}
让我们快速浏览这里发生的事情:
-
start
方法定义了身份验证的入口点。这里的目标是将用户重定向到Discord的门户(换句话说,启动OAuth2进程)。如您所见,它引用了我们尚未创建的路由。 -
supports
方法定义了当前请求是否必须由我们的身份验证器支持。仅当当前路由是我们之前创建的登录路线时,才会发生。 -
authenticate
方法是身份验证者的核心。它必须返回一个将包含用户进行身份验证的koude18。 -
onAuthenticationSuccess
定义了我们的后认证过程。我们主要想将用户重定向到他们的主页。 -
onAuthenticationFailure
允许您与身份验证失败相互作用。
现在我们的身份验证者都设置了,让我们知道它是由身份验证的。现在,让我们打开config/packages/security.yaml
文件,并使其看起来像这样:
security:
providers:
users:
entity:
class: 'App\Entity\User'
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: users
custom_authenticators:
- App\Security\DiscordAuthenticator
logout:
path: app_logout
target: app_index
Symfony现在意识到您正在使用User
实体通过App\Security\DiscordAuthenticator
Authenticator对用户进行身份验证。
但是
我们还没有完成ð
使用户实体对身份验证友好
按照Symfony建立身份验证的方式,我们现在必须使我们的User
实体实现UserInterface
。现在应该看起来像这样:
#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $discordId = null;
// getters and setters
public function getRoles(): array
{
// TODO: Implement getRoles() method.
}
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
public function getUserIdentifier(): string
{
// TODO: Implement getUserIdentifier() method.
}
}
本教程并非旨在潜入Symfony身份验证。如果您需要有关用户的更多信息,click here。
创建入口点
回到身份验证器,别忘了入口点!为了设置它,让我们回到我们的DiscordController
,然后添加auth_discord_start
路线:
#[Route("/start", name: "start")]
public function start(ClientRegistry $clientRegistry): RedirectResponse
{
return $clientRegistry->getClient("discord")->redirect(["identify"]);
}
在此方法中,我们从注册表中获取了client cam discord
。 discord
这个名字并非无处不在。确实,这是我们在KNP捆绑包的YAML配置中较早设置的。如果您在yaml中做到了,请不要忘记更改名称。
获得合适的客户端后,我们调用redirect
方法,以将用户重定向到Discord身份验证门户。请注意,我们将list of scopes设置为[identify]
。它将允许客户向/users/@me
URL提出请求并收集用户的信息。
现在已经设置了所有这些,您现在可以在UI中添加一个按钮,将其重定向到此URL。用户在此URL上,它将被重定向到Discord身份验证门户:
好吧,是的,这不是重点。
用户单击“ Autoriser”按钮后,应将其重定向到/auth/discord/login
URL,并以code
查询参数的形式稍有奖励。此代码将用于检索访问令牌,该代币在此处自动完成。
在对我们的DEV环境进行测试时,经过身份验证,我们应该能够使用Symfony Web调试工具栏目睹身份验证成功:
如果是这样,好工作,我们的完整oauth2身份验证过程已完成并成功!
结束登记
嘿!稍等一下 !我们不是忘记了什么吗?不用担心,与Symfony断开用户非常容易。确实,您已经开始配置要记录用户的方式!
在config/packages/security.yaml
文件中,我们补充说:
logout:
path: app_logout
target: app_index
本部分定义了我们的注销路由名称是app_logout
,并且将用户重定向到app_index
。
我们现在需要做的就是声明注销路线:
namespace App\Controller;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;
#[AsController]
final class SecurityController
{
#[Route('/logout', name: 'app_logout')]
public function logout()
{
throw new \Exception('Logging out');
}
}
结论
感谢您一直关注本教程的人。我希望对您有所帮助,一切都清楚。我本可以在某些时候更深入,但是您知道,该教程必须保持可读!
更重要的是,我希望您明白了OAuth2!在本教程中,我们使用不和谐。值得庆幸的是,他们有一个干净的OAuth2系统,可以帮助您介绍该协议。一旦理解协议,这只是实施的问题!
如果需要,请去查看本教程的Github repository。
再次感谢您阅读我的第一篇文章。如果您需要更多任何解释,让我们在评论部分见面!
愉快的编码,别忘了PHP没有死!