dodocierny/laravel-keycloak-web-guard

简单的Keycloak Guard到Laravel Web路由

dev-master 2024-04-05 08:10 UTC

This package is auto-updated.

Last update: 2024-09-05 08:59:12 UTC


README

[需要维护者] Laravel的Keycloak Web Guard

此包允许您使用Keycloak服务器进行用户认证。

它在前端工作。对于API,我们推荐laravel-keycloak-guard

要求

  • 拥有Keycloak服务器。
  • 已配置领域并有一个接受认证的客户端。

支持

此包已在以下环境中测试

  • Laravel: 5.8 / 7 / 8 / 9
  • Keycloak: 18.0.0

其他版本可能无法保证工作。

这是一个开源项目,在业余时间维护。因此,如果您有任何问题,可以打开一个包含所有详细信息(Laravel版本、Keycloak版本、问题的描述等)的问题,我将很高兴尝试帮助您。

流程

  1. 用户访问受保护的路由并被重定向到Keycloak登录页面。
  2. 用户登录并获得一个代码。
  3. 他将被重定向到回调页面,我们将代码更改为访问令牌。
  4. 我们将其存储在会话中并验证用户。
  5. 用户已登录。
  6. 我们将用户重定向到“redirect_url”路由(请参阅配置)或目标路由。

安装

需要此包

composer require vizir/laravel-keycloak-web-guard

如果您想更改路由或Keycloak的默认值,请发布配置文件

php artisan vendor:publish  --provider="Vizir\KeycloakWebGuard\KeycloakWebGuardServiceProvider"

配置

在发布config/keycloak-web.php文件后,您可以更改路由

'redirect_url' => '/admin',

'routes' => [
    'login' => 'login',
    'logout' => 'logout',
    'register' => 'register',
    'callback' => 'callback',
]

更改任何值以更改URL。

其他配置可以更改以使用新的默认值,但我们建议使用.env文件

  • KEYCLOAK_BASE_URL

Keycloak服务器URL。通常是类似这样的东西:https://your-domain.com/auth

  • KEYCLOAK_REALM

Keycloak领域。默认为master

  • KEYCLOAK_REALM_PUBLIC_KEY

Keycloak服务器领域公钥(字符串)。

在仪表板上,请转到:Keycloak >> 领域设置 >> 密钥 >> RS256 >> 公钥。

  • KEYCLOAK_CLIENT_ID

Keycloak客户端ID。

在仪表板上,请转到:Keycloak >> 客户端 >> 安装。

  • KEYCLOAK_CLIENT_SECRET

Keycloak客户端密钥。如果为空,我们不会将其发送到令牌端点。

在仪表板上,请转到:Keycloak >> 客户端 >> 安装。

  • KEYCLOAK_CACHE_OPENID

我们可以缓存OpenId配置:这是我们要求Keycloak的端点列表。

如果您激活它,请记住在更改领域或URL时清除缓存。

只需将您希望作为数组添加到“to”选项中即可,例如将“to”添加到keycloak-web.php配置文件中的guzzle_options数组。例如

Laravel Auth

您应将Keycloak Web guard添加到您的config/auth.php中。

只需将keycloak-web添加到您想要配置的配置的“driver”选项上。

由于我的默认是web,因此我将其添加到其中

'guards' => [
    'web' => [
        'driver' => 'keycloak-web',
        'provider' => 'users',
    ],

    // ...
],

并更改您的提供者配置

'providers' => [
    'users' => [
        'driver' => 'keycloak-users',
        'model' => Vizir\KeycloakWebGuard\Models\KeycloakUser::class,
    ],

    // ...
]

注意:如果您想使用其他用户模型,请查看FAQ 如何实现我的模型?

API

我们实现了Illuminate\Contracts\Auth\Guard。因此,所有Laravel默认方法都将可用。

例如:Auth::user()返回已认证的用户。

角色

您可以通过Auth::hasRole('role')简单地检查用户是否有角色;

此方法接受两个参数:第一个是角色(字符串或字符串数组),第二个是资源。

如果没有提供,资源将是client_id,这是你验证进入此客户端到前端的常规检查。

Keycloak Web网关

你可以使用Laravel授权网关来检查用户是否具有一个或多个角色(和资源)。

例如,在你的控制器中你可以检查一个角色

if (Gate::denies('keycloak-web', 'manage-account')) {
  return abort(403);
}

或者多个角色

if (Gate::denies('keycloak-web', ['manage-account'])) {
  return abort(403);
}

以及资源的角色

if (Gate::denies('keycloak-web', 'manage-account', 'another-resource')) {
  return abort(403);
}

最后一个用法并不简单,但你可以通过扩展Guard来请求对多个资源的认证/授权。默认情况下,我们只请求当前客户端。

Keycloak可中间件

如果你不想使用网关或已经实现了中间件,你可以使用keycloak-web-can中间件来检查用户是否具有一个或多个角色。

将此添加到你的控制器__construct方法中

$this->middleware('keycloak-web-can:manage-something-cool');

// For multiple roles, separate with '|'
$this->middleware('keycloak-web-can:manage-something-cool|manage-something-nice|manage-my-application');

此中间件默认搜索所有角色和资源(client_id)。

你可以扩展它并在Kernel.php中注册自己的中间件,或者只需在控制器中使用Auth::hasRole($roles, $resource)

常见问题解答

如何实现我的模型?

我们在config/auth.php中注册了一个名为"keycloak-users"的新用户提供者。

在这个相同的配置中,你设置了模型。因此,你可以注册自己的模型,通过扩展Vizir\KeycloakWebGuard\Models\KeycloakUser类并更改此配置来实现。

你可以实现自己的用户提供者:只需记住要实现retrieveByCredentials方法,接收Keycloak配置文件信息以检索模型的一个实例。

Eloquent/数据库用户提供者应该运行良好,因为它们将解析Keycloak配置文件并对你的数据库进行“where”操作。因此,你的用户数据必须与Keycloak配置文件相匹配。

我找不到我的登录表单。

我们注册了一个login路由以重定向到Keycloak服务器。登录后,我们将接收并处理令牌以认证你的用户。

没有登录/注册表单。

如何保护路由?

只需添加keycloak-web中间件

// On RouteServiceProvider.php for example

Route::prefix('admin')
  ->middleware('keycloak-web')
  ->namespace($this->namespace)
  ->group(base_path('routes/web.php'));

// Or with Route facade in another place

Route::group(['middleware' => 'keycloak-web'], function () {
    Route::get('/admin', 'Controller@admin');
});

访问/刷新令牌和状态在哪里持久化?

在会话中。如果你有负载均衡,我们建议实现数据库驱动。

什么是状态?

状态是一个唯一且难以猜测的字符串,用于减轻CSRF攻击。

我们将每个即将发起的认证请求与一个随机状态关联,并在回调中检查。如果你正在扩展/实现自己的Auth控制器,你应该这样做。

使用KeycloakWeb::saveState()方法将已生成的状态保存到会话中,使用KeycloakWeb::validateState()方法检查当前状态与保存的状态是否一致。

我在会话(卡在登录循环)上遇到问题。

由于某些原因,Laravel可能会遇到EncryptCookies中间件更改会话ID的问题。

在这种情况下,我们总是会尝试登录,因为无法检索令牌。

你可以从加密中移除session_id cookie。

// On your EncryptCookies middleware

class EncryptCookies extends Middleware
{
    protected $except = [];

    public function __construct(EncrypterContract $encrypter)
    {
        parent::__construct($encrypter);

        /**
         * This will disable in runtime.
         *
         * If you have a "session.cookie" option or don't care about changing the app name
         * (in another environment, for example), you can only add it to "$except" array on top
         */
        $this->disableFor(config('session.cookie'));
    }
}

我的客户端不是公开的。

如果你的客户端不是公开的,你应该在.env中提供KEYCLOAK_CLIENT_SECRET

如何覆盖默认的Guzzle选项?

在某些情况下,你可能需要覆盖默认的Guzzle选项——可能是禁用SSL验证或将代理设置为一个路由所有请求通过的对象。

每个Guzzle请求选项都受支持,并直接传递给Guzzle客户端实例。

只需将你希望在keycloak-web.php配置文件中添加的选项添加到guzzle_options数组中。例如

'guzzle_options' => [
    'verify' => false
]

开发者

GitHub上的贡献者❤️