symfonycorp / connect-bundle
Requires
- php: >=7.1.3
- symfonycorp/connect: ^6.3
Requires (Dev)
- symfony/phpunit-bridge: ^4.4|^5.0
- symfony/security-bundle: ^4.4|^5.0
Conflicts
- symfony/config: <4.2
- dev-master / 6.x-dev
- v6.2.0
- v6.1.0
- v6.0.1
- v6.0.0
- 5.1.x-dev
- v5.1.4
- v5.1.3
- v5.1.2
- v5.1.1
- v5.1.0
- 5.0.x-dev
- v5.0.4
- v5.0.3
- v5.0.2
- v5.0.0
- 4.3.x-dev
- v4.3.13
- v4.3.12
- v4.3.11
- v4.3.10
- v4.3.9
- v4.3.8
- v4.3.7
- v4.3.6
- v4.3.5
- v4.3.4
- v4.3.3
- v4.3.2
- v4.3.1
- v4.3.0
- v4.2.2
- v4.2.1
- v4.2.0
- v4.1.0
- v4.0.0
- v3.1.0
- v3.0.0
- v2.0.0
- v1.0.0
- dev-authenticator
This package is auto-updated.
Last update: 2021-06-08 16:51:33 UTC
README
关于
这是 SymfonyConnect SDK 的官方包。
安装
第1步:使用 Composer 安装 symfony/connect-bundle
$ composer require symfonycorp/connect-bundle
如果您未使用 Symfony Flex,请参考 此包的配方 以启用它。
第2步:配置您的 .env.local
文件
SYMFONY_CONNECT_APP_ID='Your app id' SYMFONY_CONNECT_APP_SECRET='Your app secret'
使用方法
使用 SymfonyConnect 验证您的用户
第1步:配置安全设置
注意:如果您想持久化用户,请阅读 食谱 部分。
如果您不想持久化用户,您可以使用 ConnectInMemoryUserProvider
# config/packages/security.yaml security: providers: symfony_connect: connect_memory: ~ firewalls: # [...] secured_area: pattern: ^/ symfony_connect: check_path: symfony_connect_callback login_path: symfony_connect_login failure_path: home # need to be adapted to your config, see step 4 remember_me: false provider: symfony_connect anonymous: true
您还可以为某些用户加载特定的角色
# config/packages/security.yaml security: providers: symfony_connect: connect_memory: users: 90f28e69-9ce9-4a42-8b0e-e8c7fcc27713: "ROLE_CONNECT_USER ROLE_ADMIN"
注意:用户名是用户 uuid。
第2步:向您的模板添加一些链接
您可以生成一个链接到 SymfonyConnect 登录页面
<a href="{{ url('symfony_connect_login') }}">Connect</a>
您还可以指定登录后的目标 URL
<a href="{{ url('symfony_connect_login') }}?target=XXX">Connect</a>
第3步:与用户互动
API 用户可以通过令牌存储获取,您可以通过自动注入 Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokenStorage
来获取。
$user = $tokenStorage->getToken()->getApiUser();
如果您使用内置的安全组件,您可以通过自动注入 SymfonyCorp\Connect\Api\Api $api
直接访问根 API
$user = $api->getRoot()->getCurrentUser();
您也可以通过显式提供访问令牌来访问 API 根对象
$accessToken = $tokenStorage->getToken()->getAccessToken(); $api->setAccessToken($accessToken); $root = $api->getRoot(); $user = $root->getCurrentUser();
第4步:处理失败
在 OAuth 舞蹈过程中可能会发生几个错误,例如用户可以拒绝您的应用程序,或者您在 symfony_connect.yaml
中定义的作用域可能与您在 SymfonyConnect 上创建应用程序时选择的不同。这些失败由默认的 Symfony 失败处理程序处理。
因此,如果发生错误,错误将被存储在会话中(在查询参数上回退),并且用户将被重定向到 security.yaml
中防火墙的 symfony_connect
部分的 failure_path
节指定的路由/路径。
警告:您必须指定
failure_path
。如果您不指定,用户将被重定向回login_path
,这意味着将启动SymfonyConnect身份验证并将用户重定向到SymfonyConnect,这可能导致重定向循环。
这意味着您需要获取身份验证错误(如果有的话)并在视图中显示它。这与您在Symfony中为典型登录表单所做的事情类似(这里我们假设您有一个指向以下控制器的home
路由)
// src/Controller/HomeController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; class HomeController extends AbstractController { /** * @Route("/", name="home") */ public function home(Request $request) { $session = $request->hasSession() ? $request->getSession() : null; // get the authentication error if there is one if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) { $error = $request->attributes->get(Security::AUTHENTICATION_ERROR); } elseif (null !== $session && $session->has(Security::AUTHENTICATION_ERROR)) { $error = $session->get(Security::AUTHENTICATION_ERROR); $session->remove(Security::AUTHENTICATION_ERROR); } else { $error = ''; } return $this->render('home.html.twig', ['error' => $error]); } }
然后调整您的twig模板
{# templates/home.html.twig #} {% if app.user %} Congrats! You are authenticated with SymfonyConnect {% elseif error %} {{ error.messageKey | trans(error.messageData, 'security') }} {% else %} <a href="{{ url('symfony_connect_login') }}">Log in with SymfonyConnect</a> {% endif %}
食谱
如何持久化用户
步骤 1 - 创建User
实体
<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use SymfonyCorp\Connect\Api\Entity\User as ConnectApiUser; use Symfony\Component\Security\Core\User\UserInterface; /** * @ORM\Table(name="user") * @ORM\Entity(repositoryClass="App\Repository\UserRepository") */ class User implements UserInterface { /** @ORM\Column(type="integer") @ORM\Id @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** @ORM\Column(type="string", length=255) */ private $uuid; /** @ORM\Column(type="string", length=255) */ private $username; /** @ORM\Column(type="string", length=255) */ private $name; public function __construct($uuid) { $this->uuid = $uuid; } public function updateFromConnect(ConnectApiUser $apiUser) { $this->username = $apiUser->getUsername(); $this->name = $apiUser->getName(); } public function getUuid() { return $this->uuid; } public function getUsername() { return $this->username; } public function getName() { return $this->name; } public function getRoles() { return ['ROLE_USER']; } public function getPassword() { } public function getSalt() { } public function eraseCredentials() { } }
步骤 2 - 创建存储库
<?php namespace App\Repository; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; class UserRepository extends ServiceEntityRepository implements UserProviderInterface { public function __construct(RegistryInterface $registry) { parent::__construct($registry, User::class); } public function loadUserByUsername($uuid) { return $this->findOneByUuid($uuid) ?: new User($uuid); } public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('class %s is not supported', get_class($user))); } return $this->loadUserByUsername($user->getUuid()); } public function supportsClass($class) { return User::class === $class; } }
不要忘记更新您的数据库。
步骤 3 - 创建事件监听器
<?php namespace App\EventListener; use Doctrine\ORM\EntityManagerInterface; use SymfonyCorp\Connect\Security\Authentication\Token\ConnectToken; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; class SecurityInteractiveLoginListener implements EventSubscriberInterface { private $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } public function registerUser(InteractiveLoginEvent $event) { $token = $event->getAuthenticationToken(); if (!$token instanceof ConnectToken) { return; } $user = $token->getUser(); $user->updateFromConnect($token->getApiUser()); $this->em->persist($user); $this->em->flush($user); } public static function getSubscribedEvents() { return [ SecurityEvents::INTERACTIVE_LOGIN => 'registerUser', ]; } }
步骤 4 - 配置安全
# config/packages/security.yaml security: encoders: App\Entity\User: plaintext providers: symfony_connect: id: App\Repository\UserRepository
步骤 5 - 享受
如果您想的话,可以存储更多内容。但不要忘记更新您的应用程序作用域。
许可
此软件包采用MIT许可。