slashid/symfony

该包最新版本(1.0.0)没有可用的许可证信息。

SlashID集成包,适用于Symfony。

维护者

详细信息

github.com/slashid/symfony

来源

问题

安装: 0

依赖: 0

建议者: 0

安全: 0

星标: 1

关注者: 0

分支: 0

开放问题: 0

语言:JavaScript

1.0.0 2024-05-03 17:13 UTC

This package is not auto-updated.

Last update: 2024-09-24 22:35:32 UTC


README

安装

  1. 使用composer安装包含Symfony的SlashID包
composer require slashid/symfony
  1. 编辑环境文件.env,在文件末尾添加以下变量
    • SLASHID_ENVIRONMENT,可以是sandboxproduction
    • SLASHID_ORGANIZATION_ID,您的组织ID。您可以在SlashID控制台中找到它(生产环境:https://console.slashid.dev/,沙盒环境:https://console.sandbox.slashid.dev/),在“设置”选项卡中,页面顶部。
    • SLASHID_API_KEY,您的组织API密钥。您也可以在SlashID控制台中找到它,在“设置”选项卡中,页面底部。
# .env

SLASHID_ENVIRONMENT=sandbox
SLASHID_ORGANIZATION_ID=412edb57-ae26-f2aa-9999-770021ed52d1
SLASHID_API_KEY=z0dlY-nluiq8mcvm8YTolSkJV6e9
  1. 运行Symfony命令以发布包资源
php bin/console assets:install
  1. 编辑config/routes.yaml,在文件末尾添加以下内容
# config/routes.yaml

_slashid_symfony_bundle:
    resource: '@slashid/config/routes.yaml'
  1. 编辑config/packages/security.yaml,添加以下SlashID引用
# config/packages/security.yaml

security:
    providers:
        slashid:
          id: slashid.user_provider

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: slashid
            custom_authenticators:
                - slashid.authenticator
            logout:
                path: /logout

您已经准备好了!现在访问网站中的/login并享受SlashID的新登录吧 :)

无状态登录

如果您的Symfony安装作为API后端(例如React应用程序)运行,您可能需要配置无状态登录。要这样做,只需将stateless: true添加到防火墙配置中,例如

# config/packages/security.yaml

security:
    # ................
    firewalls:
        api:
            pattern: ^/api
            provider: slashid
            custom_authenticators:
                - slashid.authenticator
            stateless: true
        main:
            lazy: true
            provider: slashid
            custom_authenticators:
                - slashid.authenticator

在上面的示例中,任何对/api/****的请求将通过发送Authorization: Bearer <<TOKEN>>头中的SlashID令牌进行登录。所有其他路由将使用cookie进行登录。

⚠️ 注意!如果您不添加stateless: true,则带有Authorization: Bearer <<TOKEN>>头的请求将创建cookie登录。

配置

如果您想通过在Symfony安装中创建config/packages/slashid.yaml文件来自定义SlashID集成,例如

# config/packages/slashid.yaml

slashid:
    login_form:
        configuration:
            analytics-enabled: false
            theme-props:
                theme: dark
            factors:
                - { "method": "webauthn" }
                - { "method": "email_link" }
                - { "method": "password" }
        css_override:
            --sid-color-primary: "#f00"
            --sid-color-primary-hover: "#900"

    route_after_login: 'dashboard'

这些是配置选项

登录表单配置

登录表单是SlashID的React SDK的捆绑版本。因此,组件中所有选项在这里都是可用的,只需注意您必须将camelCase转换为kebab-case(见以下示例)。

例如,要使用深色主题,请这样做

# config/packages/slashid.yaml

slashid:
    login_form:
        configuration:
            theme-props:
                theme: dark

如果您想启用密码登录并禁用电子邮件链接登录,请这样做

# config/packages/slashid.yaml

slashid:
    login_form:
        configuration:
            factors:
                - { "method": "webauthn" }
                - { "method": "password" }

您还可以覆盖由React SDK提供的任何CSS变量。例如,要使登录按钮为红色,悬停时颜色更深,可以这样做

# config/packages/slashid.yaml

slashid:
    login_form:
        css_override:
            --sid-color-primary: "#f00"
            --sid-color-primary-hover: "#900"

基于组的路由访问

SlashID中的组作为Symfony角色公开。因此,例如,如果您有一个名为“编辑器”的组,则用户将具有ROLE_EDITOR角色。

您可以通过编辑security.yaml来保护基于SlashID组的路由,如下所示

# config/packages/security.yaml

security:
    # ..........

    access_control:
        - { path: "^/editor", roles: ROLE_EDITOR }
        - { path: ^/admin, roles: ROLE_ADMIN }

⚠️ 注意!所有组名称都将大写,因此名为“编辑器”、“editor”和“EDITOR”的组都将转录为ROLE_EDITOR

在自定义代码中检查组

如果您想检查自定义代码中用户的组,您可以使用\SlashId\Symfony\SlashIdUser类的任何与组相关的函数,例如

// src/Controller/MyCustomController.php

namespace App\Controller;

<?php

namespace App\Controller;

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

class TestController extends AbstractController
{

    #[Route('/my-test-route')]
    public function testRoute(): Response
    {
        /** @var \SlashId\Symfony\SlashIdUser */
        $user = $this->getUser();

        if ($user->hasGroup('Editor')) {
            // Do things that only an "Editor" user can do.
        }

        if ($user->hasAnyGroup(['Admin', 'Editor', 'Reviewer'])) {
            // Do things that someone in the group "Admin", OR in the group
            // "Editor", OR in the group "Reviewer" can do.
        }

        if ($user->hasAllGroups(['Admin', 'Editor'])) {
            // Do things that only someone that is in *both* "Admin" and
            // "Editor" groups can do.
        }

        // Shows the user groups as a list of strings.
        dd($user->getGroups());
    }
}

在Twig中检查组

您还可以使用hasGroup / hasAnyGroup / hasAllGroups方法来构建Twig模板,根据用户所属的组显示不同内容。

{# templates/test.html.twig #}

{% if app.user %}

    <p>You are logged in</p>

    {% if app.user.hasGroup('Editor') %}
        <p>Information Editors can access.</p>

    {% endif %}

    {% if app.user.hasGroup('Admin') %}

        <p>Information Admins can access.</p>

    {% endif %}

    {% if app.user.hasAnyGroup(['Admin', 'Editor']) %}

        <p>Information both Editors and Admins can access.</p>

    {% endif %}

    {{ dump(app.user.getGroups()) }}

{% else %}

    <p>You are NOT logged in</p>

{% endif %}

Webhooks

查看SlashID关于Webhooks的文档

CLI webhook命令

要使用webhooks,您需要首先在SlashID中注册您的URL。webhooks通过API管理,但此包提供了三个CLI命令来帮助您管理它们。

如何注册webhooks

要为当前网站注册新的webhook,请使用以下命令。您需要为它定义一个唯一的名称,在此示例中,我们使用my_webhook

php bin/console slashid:webhook:register my_webhook

默认情况下,webhook注册了以下触发器:PersonDeleted_v1PersonLoggedOut_v1PasswordChanged_v1。您可以指定要注册哪些触发器,使用空格分隔触发器列表

php bin/console slashid:webhook:register my_webhook PasswordChanged_v1 VirtualPageLoaded_v1 AuthenticationFailed_v1

您可以多次运行slashid:webhook:register,如果已在该URL注册了webhook,则它将被更新,并且触发器列表将被覆盖。

如何在本地测试webhooks

您可以使用类似ngrok的工具在本地开发环境中测试webhooks,然后使用--base-url选项注册具有代理的webhook。

例如,如果您在8080端口上运行Symfony,可以使用以下命令使用ngrok代理您的本地环境:

ngrok http 8000

ngrok命令行将显示有关代理的数据,例如:

Forwarding                    https://2f45-2804-14c-483-983f-b323-32f2-4714-1609.ngrok-free.app -> https://:8000

然后,您可以使用以下命令将Web服务注册到代理URL:

php bin/console slashid:webhook:register proxied_webhook PasswordChanged_v1 --base-url=https://2f45-2804-14c-483-983f-b323-32f2-4714-1609.ngrok-free.app

如何为其他应用程序注册webhooks

您可以使用CLI命令将webhooks注册到任何任意URL

php bin/console slashid:webhook:register proxied_webhook PasswordChanged_v1 --webhook-url=https://someotherapplication.example.com/some-arbitrary-url

如何查看现有webhooks

您可以使用以下命令查看您SlashID组织中注册的所有webhooks:

php bin/console slashid:webhook:list

如何删除webhook

您可以通过ID删除webhook。

php bin/console slashid:webhook:delete 065e5237-c1c4-7a96-ab00-783ef0cbd002

要了解webhook ID,请使用slashid:webhook:list命令。

监听事件

任何接收到的webhook都将作为Symfony事件提供给开发者。

要在您的Symfony应用程序中监听webhook事件,在您的应用程序的src/EventListener文件夹中创建一个类。在下面的示例中,我们将其命名为WebhookEventListener,但您可以随意命名。

// src/EventListener/WebhookEventListener.php

namespace App\EventListener;

use SlashId\Symfony\Event\WebhookEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

#[AsEventListener]
class WebhookEventListener
{
    public function __invoke(WebhookEvent $event): void
    {
        print_r([
            $event->getEventName(),
            $event->getEventId(),
            $event->getTriggerContent(),
        ]);
    }
}

监听器将接收类为\SlashId\Symfony\Event\WebhookEvent的事件。它有三个方法,您可以使用它们提取有关webhook调用的信息

  • $event->getEventName()将返回触发器名称,例如AuthenticationFailed_v1,即在发送到webhook的JSON中的->trigger_content->event_metadata->event_name
  • $event->getEventId()将返回事件ID,例如68a850ca-b2ee-46ce-8592-410813037739,即在发送到webhook的JSON中的->trigger_content->event_metadata->event_id
  • $event->getTriggerContent()将返回webhook调用的全部内容,即在发送到webhook的JSON中的->trigger_content

重写路由

默认情况下,Symfony包公开了三个路由

  • /login - 登录表单
  • /login/callback - 背景中调用的路由以完成登录过程
  • /slashid/webhook - webhook监听器

在某些情况下,您可能不想公开webhook或登录表单,甚至可能要更改这些路由的URL。为了完成此操作,首先从config/routes.yaml中删除_slashid_symfony_bundle:行,然后手动添加路由

# config/routes.yaml

# Remove the two lines below.
#_slashid_symfony_bundle:
#    resource: '@slashid/config/routes.yaml'

slashid.login:
    path: /custon-path-for-login
    controller: SlashId\Symfony\Controller\LoginController::login

slashid.login.callback:
    path: /custon-path-for-login/callback
    controller: SlashId\Symfony\Controller\LoginController::loginCallback

# In this example we don't enable the webhook listener.
#slashid.webhook:
#    path: /slashid/webhook
#    controller: SlashId\Symfony\Controller\WebhookController::webhook

⚠️ 注意:您必须保留路由名称:slashid.loginslashid.login.callbackslashid.webhook

用户迁移

如果您在现有的Symfony网站上安装SlashID,您可能已经有一个您希望迁移到SlashID数据库的用户基础。这可以通过两个迁移命令轻松实现。

首先,您必须运行命令php bin/console slashid:import:create-script。它将询问您安装中的用户类,通常是\App\Models\User

$ php bin/console slashid:import:create-script

 Please inform the class of the user model [\App\Entity\User]:
 >


 [OK] The Slash ID migration script has been created at
      /var/www/symfony/migrations/slashid/user-migration.php. Please open the file and modify it
      according to the instructions in it.

将在migrations/slashid/user-migration.php中创建一个脚本(可以通过修改migration_script_folder选项来自定义文件夹目标)。它看起来是这样的:

<?php

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use SlashId\Php\PersonInterface;
use SlashId\Symfony\SlashIdUser;

return static function (EntityManagerInterface $entityManager): array {
    /** @var array<User> */
    $doctrineUsers = $entityManager->getRepository(User::class)->findAll();
    $slashIdUsers = [];

    foreach ($doctrineUsers as $doctrineUser) {
        $roles = $doctrineUser->getRoles();
        unset($roles[array_search('ROLE_USER', $roles)]);

        // Converts "ROLE_ADMIN" into "Admin".
        $roles = array_map(fn (string $role) => ucwords(strtolower(str_replace('_', ' ', str_replace('ROLE_', '', $role)))), $roles);

        $slashIdUser = new SlashIdUser();
        $slashIdUser
            ->addEmailAddress($doctrineUser->getEmail())
            ->setLegacyPasswordToMigrate($doctrineUser->getPassword())
            // Uncomment if you want to set the phone number.
            // ->addPhoneNumber($doctrineUser->getPhoneNumber())
            ->setGroups($roles)
            // Uncomment if you want to specify a region for the user.
            // ->setRegion('us-iowa')
            ->setBucketAttributes(PersonInterface::BUCKET_ORGANIZATION_END_USER_NO_ACCESS, [
                // List the user attributes you want to migrate, grouped by bucket.
                'old_id' => $doctrineUser->getUserIdentifier(),
                // 'first_name' => $doctrineUser->getFirstName(),
                // 'last_name' => $doctrineUser->getLastName(),
            ])
        ;

        $slashIdUsers[] = $slashIdUser;
    }

    return $slashIdUsers;
};

您必须修改user-migration.php以根据需要建模要迁移的数据,特别是添加您想要的属性。脚本必须返回一个包含您想要批量导入到SlashID的所有用户的\SlashId\Symfony\SlashIdUser数组。

根据您的需求修改脚本后,运行php bin/console slashid:import:run,例如:

$ php bin/console slashid:import:run
+------------------------+---------------+--------+-------+--------+-------------------------------------------------------------------------------------------------------------------------------+
| Emails                 | Phone numbers | Region | Roles | Groups | Attributes                                                                                                                    |
+------------------------+---------------+--------+-------+--------+-------------------------------------------------------------------------------------------------------------------------------+
| rattazzi@example.com   |               |        |       |        | {"end_user_no_access":{"old_id":1,"firstname":"Urbano","email_verified_at":null,"lastname":"Rattazzi","username":"rattazzi"}} |
| nitti@example.com      |               |        |       |        | {"end_user_no_access":{"old_id":2,"firstname":"Francesco","email_verified_at":null,"lastname":"Nitti","username":"nitti"}}    |
| cavour@example.com     |               |        |       |        | {"end_user_no_access":{"old_id":3,"firstname":"Camillo","email_verified_at":null,"lastname":"Cavour","username":"cavour"}}    |
+------------------------+---------------+--------+-------+--------+-------------------------------------------------------------------------------------------------------------------------------+

 Do you want to proceed with importing 3 users? (yes/no) [no]:
 > yes

2 successfully imported users.
1 users failed to import. Check the file /var/www/symfony/migrations/slashid/migration-failed-202403271142.csv for errors.

迁移过程中出现的任何错误将以CSV格式输出。检查CSV以修复错误并再次运行。

覆盖登录表单

Twig模板以及如何在布局中插入表单

登录表单在Twig模板templates/login/login.html.twig中渲染,该模板继承自base.html.twig,因此登录表单被网站的默认布局所包围。

如果您想更改模板,将文件vendor/slashid/symfony/templates/login/login.html.twig复制到templates/bundles/slashid/login/login.html.twig并按需修改。

使用自定义JavaScript

Laravel包附带了一个SlashID React SDK的包和一小段位于vendor/slashid/symfony/public/slashid.symfony-web-login.js中的JavaScript粘合代码。

您可能想覆盖捆绑的React SDK以编译您的React登录表单实现。如果是这样,将config/packages/slashid.yaml中的选项slashid.login_form.override_bundled_javascript更改为true以防止加载捆绑的React SDK。

或者,您可能想覆盖粘合代码,在登录后包含自定义操作。如果是这样,将选项slashid.login_form.override_javascript_glue更改为true以防止加载粘合代码。

在这两种情况下,您都需要自行加载您的自定义代码。