btrs / laravel-keycloak-web-guard
Laravel Web 路由简单 Keycloak 守卫
Requires
- guzzlehttp/guzzle: ^6.5|^7.0
This package is not auto-updated.
Last update: 2024-09-22 00:23:16 UTC
README
Laravel Keycloak Web 守卫
此包允许您使用 Keycloak 服务器 认证用户。
它在前端工作。对于 API,我们推荐 laravel-keycloak-guard。
要求
- 拥有 Keycloak 服务器。
- 拥有配置的 realm 和接受身份验证的客户端。
支持
此包已在以下版本上进行测试:
- Laravel: 5.8 / 7 / 8 / 9
- Keycloak: 18.0.0
其他版本不保证工作。
这是一个开源项目,我会在业余时间维护。所以,如果您有任何问题,您可以提交一个包含所有详细信息(Laravel 版本、Keycloak 版本、问题描述等)的问题,我会很高兴尝试帮助您。
流程
- 用户访问受保护的路由并被重定向到 Keycloak 登录。
- 用户登录并获得一个代码。
- 他被重定向到回调页面,我们将代码更改为访问令牌。
- 我们将其存储在会话中并验证用户。
- 用户已登录。
- 我们将用户重定向到“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 realm。默认为 master
。
KEYCLOAK_REALM_PUBLIC_KEY
Keycloak 服务器 realm 公钥(字符串)。
在仪表板中转到:Keycloak >> Realm Settings >> Keys >> RS256 >> Public Key。
KEYCLOAK_CLIENT_ID
Keycloak 客户端 ID。
在仪表板中转到:Keycloak >> Clients >> Installation。
KEYCLOAK_CLIENT_SECRET
Keycloak 客户端密钥。如果为空,则不会将其发送到令牌端点。
在仪表板中转到:Keycloak >> Clients >> Installation。
KEYCLOAK_CACHE_OPENID
我们可以缓存 OpenId 配置:这是我们要求 Keycloak 的端点列表。
如果您激活它,请记住在更改 realm 或 URL 时刷新缓存。
只需将您希望添加的选项作为数组添加到 "to" Just add the options you would like to guzzle_options array on keycloak-web.php config file. 例如
Laravel Auth
您应将 Keycloak Web 守卫添加到您的 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); }
最后一个用法不简单,但您可以扩展守卫以请求对多个资源的认证/授权。默认情况下,我们只请求当前客户端。
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
]
开发者
- Mário Valney @mariovalney
- Vizir软件工作室
GitHub上的贡献者❤️