spinen/laravel-discourse-sso

将 Discourse SSO 集成到 Laravel。

2.9.1 2024-04-14 21:40 UTC

README

Latest Stable Version Latest Unstable Version Total Downloads License

Discourse 是一款优秀的在线论坛软件,支持单点登录 (SSO)。有一个优秀的 PHP 库可以处理所有繁重的工作,使 SSO 能够工作,这个库叫做 cviebrock/discourse-php,这个包就是基于这个库开发的。这个包是基于 jaewun/discourse-sso-laravel 的作品。

构建状态

先决条件

注意:如果您需要使用 < PHP 7.2,请继续使用版本 1.x

除了 Laravel >= 5.5 之外,还需要 1 个包。

安装

安装 Laravel 的 Discourse SSO

$ composer require spinen/laravel-discourse-sso

该包使用 Laravel 5 的 自动注册功能

包配置

所有配置值都存储在 config/services.php 中的 discourse 键下。以下是需要添加的数组...

    'discourse' => [
        // Middleware for the SSO login route to use
        'middleware' => ['web', 'auth'],

        // The route's URI that acts as the entry point for Discourse to start the SSO process.
        // Used by Discourse to route incoming logins.
        'route' => 'discourse/sso',

        // Optional domain to link sso route when using SSubdomain Routing
        'domain' => null,

        // Secret string used to encrypt/decrypt SSO information,
        // be sure that it is 10 chars or longer
        'secret' => env('DISCOURSE_SECRET'),

        // Disable Discourse from sending welcome message
        'suppress_welcome_message' => 'true',

        // Where the Discourse forum lives
        'url' => env('DISCOURSE_URL'),

        // Api-specific items
        // For logging out of Discourse directly, generate an API key as an "All user key" and put the key & user here.
        // @see https://meta.discourse.org/t/how-to-create-an-api-key-on-the-admin-panel/87383
        'api' => [
            'key' => env('DISCOURSE_API_KEY'),
            'user' => env('DISCOURSE_API_USER'),
        ],

        // User-specific items
        // NOTE: The 'email' & 'external_id' are the only 2 required fields
        'user' => [
            // Check to see if the user has forum access & should be logged in via SSO
            'access' => null,

            // Discourse Groups to make sure that the user is part of in a comma-separated string
            // NOTE: Groups cannot have spaces in their names & must already exist in Discourse
            'add_groups' => null,

            // Boolean for making the user a Discourse admin. Leave null to ignore
            'admin' => null,

            // Full path to user's avatar image
            'avatar_url' => null,

            // The avatar is cached, so this triggers an update
            'avatar_force_update' => false,

            // Content of the user's bio
            'bio' => null,

            // Verified email address (see "require_activation" if not verified)
            'email' => 'email',

            // Unique string for the user that will never change
            'external_id' => 'id',

            // Boolean for making user a Discourse moderator. Leave null to ignore
            'moderator' => null,

            // Full name on Discourse if the user is new or
            // if SiteSetting.sso_overrides_name is set
            'name' => 'name',

            // Discourse Groups to make sure that the user is *NOT* part of in a comma-separated string.
            // NOTE: Groups cannot have spaces in their names & must already exist in Discourse
            // There is not a way to specify the exact list of groups that a user is in, so
            // you may want to send the inverse of the 'add_groups'
            'remove_groups' => null,

            // If the email has not been verified, set this to true
            'require_activation' => false,

            // username on Discourse if the user is new or
            // if SiteSetting.sso_overrides_username is set
            'username' => 'email',
        ],
    ],

user 属性的值可以是以下 4 个值之一...

  1. false -- 传递给 Discourse
  2. true -- 传递给 Discourse
  3. null -- 禁止向 Discourse 发送属性
  4. 一个 string -- User 模型上的属性名称

然后您可以在 访问器 中添加逻辑到 User 模型,以提供为用户配置的属性值。例如,如果您想任何电子邮件地址匹配 "yourdomain.tld" 的用户成为版主,则可以将 moderator 属性设置为类似于 discourse_moderator 的字符串,并在您的 User 模型中添加以下内容...

    /**
     * Is the user a Discourse moderator?
     *
     * @param  string  $value
     * @return boolean
     */
    public function getDiscourseModeratorAttribute($value)
    {
        return ends_with($this->email, "yourdomain.tld");
    }

Discourse 配置

设置 -> 登录

以下是我们在 设置 -> 登录 下的配置。如果没有列出设置,则我们将其设置为默认值。

设置 -> 用户

以下是我们在 设置 -> 用户 下的配置。如果没有列出设置,则我们将其设置为默认值。

退出 Discourse 用户

src/Listeners/LogoutDiscourseUser.php 中有一个监听器,当触发某些事件时,会自动从 Discourse 中注销用户。要使用监听器,您需要在您的 EventServiceProvider 中的 $listen 数组中 注册事件

当 Laravel 的 User 注销时,要注销其 Discourse 会话,只需在 $listen 数组中添加 Laravel 的 Logout 事件和 LogoutDiscourseUser 监听器即可。如果您想在 Laravel User 被删除或禁用时注销 Discourse 用户,请创建自己的事件类并以相同的方式注册它。

示例

    protected $listen = [
        \Illuminate\Auth\Events\Logout::class => [
            \Spinen\Discourse\Listeners\LogoutDiscourseUser::class,
        ],
        \App\Events\YourCustomEvent::class => [
            \Spinen\Discourse\Listeners\LogoutDiscourseUser::class,
        ],
    ];

Laravel 11

在 Laravel 11 中,不建议使用 EventServiceProvider,事件应该注册在 AppServiceProvider 中。具体注册方法请参考文档

因此,实现方式略有不同,应该按照以下示例,在 AppServiceProviderboot 方法中注册。

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Event::listen(
            \Illuminate\Auth\Events\Logout::class,
            \Spinen\Discourse\Listeners\LogoutDiscourseUser::class
        );
    }

待完成

  • 用户徽章
  • custom_fields 的支持
  • 登录失败后的重定向
  • return_paths 支持