PHP应用对接Keycloak身份认证基础实现相关问题咨询
Keycloak 自研PHP应用集成分步指南
前置准备(已完成的可跳过)
- Keycloak 服务端正常运行,自定义SPI功能校验通过
- Keycloak 侧创建对应客户端:
- 客户端协议选
openid-connect,访问类型设为confidential - 配置重定向URI为你的PHP应用回调地址
- 开启你需要的scope,配置自定义claims的映射规则
- 保存客户端ID、客户端密钥、Realm地址备用
- 客户端协议选
场景1:原生PHP应用集成
步骤1:安装OIDC客户端依赖
通过composer安装通用OIDC客户端库:
composer require jumbojett/openid-connect-php
步骤2:实现身份认证逻辑
新建认证入口文件,示例代码如下:
<?php require __DIR__ . '/vendor/autoload.php'; use Jumbojett\OpenIDConnectClient; $oidc = new OpenIDConnectClient( 'https://你的Keycloak地址/realms/你的Realm名称', '你的客户端ID', '你的客户端密钥' ); // 配置需要请求的scope $oidc->addScope(['openid', 'profile', 'email', '你自定义的scope']); // 禁用SSL校验(仅开发环境用,生产环境必须删掉) $oidc->setVerifyHost(false); $oidc->setVerifyPeer(false); try { // 自动处理授权码回调、token校验 $oidc->authenticate(); // 获取用户基础信息 $userInfo = $oidc->requestUserInfo(); // 获取原始access token payload(包含scopes、roles、自定义claims) $accessTokenPayload = $oidc->getAccessTokenPayload(); // 这里可以写自己的会话生成逻辑,把用户信息、权限信息存入session session_start(); $_SESSION['user'] = $userInfo; $_SESSION['permissions'] = [ 'scopes' => $accessTokenPayload->scope, 'roles' => $accessTokenPayload->realm_access->roles ?? [], 'custom_claims' => $accessTokenPayload->你自定义的claim字段 ?? [] ]; // 跳转到业务首页 header('Location: /index.php'); } catch (Exception $e) { die('认证失败:' . $e->getMessage()); }
步骤3:实现权限校验逻辑
在需要权限控制的业务接口顶部加校验逻辑:
<?php session_start(); // 先判断是否登录 if (!isset($_SESSION['user'])) { header('Location: /login.php'); exit; } // 校验是否有对应权限,比如判断是否有admin角色 if (!in_array('admin', $_SESSION['permissions']['roles'])) { http_response_code(403); die('无访问权限'); } // 校验是否有对应scope if (!str_contains($_SESSION['permissions']['scopes'], 'order:read')) { http_response_code(403); die('无订单查看权限'); } // 后续业务逻辑
场景2:Laravel 框架集成
步骤1:安装依赖
composer require socialiteproviders/keycloak
步骤2:修改配置
在config/services.php中添加Keycloak配置:
'keycloak' => [ 'client_id' => env('KEYCLOAK_CLIENT_ID'), 'client_secret' => env('KEYCLOAK_CLIENT_SECRET'), 'redirect' => env('KEYCLOAK_REDIRECT_URI'), 'base_url' => env('KEYCLOAK_BASE_URL'), 'realm' => env('KEYCLOAK_REALM'), ],
在.env文件中添加对应参数:
KEYCLOAK_CLIENT_ID=你的客户端ID KEYCLOAK_CLIENT_SECRET=你的客户端密钥 KEYCLOAK_REDIRECT_URI=https://你的Laravel应用地址/auth/callback KEYCLOAK_BASE_URL=https://你的Keycloak地址 KEYCLOAK_REALM=你的Realm名称
步骤3:配置路由
在routes/web.php中添加认证相关路由:
Route::get('/auth/login', function () { return Socialite::driver('keycloak')->scopes(['openid', 'profile', 'email', '自定义scope'])->redirect(); })->name('login'); Route::get('/auth/callback', function () { $keycloakUser = Socialite::driver('keycloak')->user(); // 这里可以处理用户本地同步、会话生成逻辑 auth()->login($你自己的本地用户对象); // 把权限信息存入session或者缓存 session([ 'permissions' => [ 'scopes' => $keycloakUser->accessTokenResponseBody['scope'], 'roles' => $keycloakUser->accessTokenResponseBody['realm_access']['roles'] ?? [], 'custom_claims' => $keycloakUser->accessTokenResponseBody['自定义claim字段'] ?? [] ] ]); return redirect('/home'); });
步骤4:自定义权限校验中间件
生成中间件:
php artisan make:middleware KeycloakPermissionCheck
中间件逻辑示例:
public function handle(Request $request, Closure $next, $requiredRole = null, $requiredScope = null) { if (!auth()->check()) { return redirect()->route('login'); } $permissions = session('permissions'); if ($requiredRole && !in_array($requiredRole, $permissions['roles'])) { abort(403, '无角色权限'); } if ($requiredScope && !str_contains($permissions['scopes'], $requiredScope)) { abort(403, '无Scope权限'); } return $next($request); }
在app/Http/Kernel.php中注册中间件后就可以在路由里使用:
Route::get('/order/list', function () { // 业务逻辑 })->middleware('keycloak.permission:user,order:read');
核心逻辑说明
- 身份认证全程走OIDC授权码流,所有和Keycloak的交互、签名校验、token刷新都由封装好的库处理,不需要手动实现。
- Keycloak返回的access token payload中包含所有你配置的scopes、角色、自定义SPI返回的自定义claims,直接解析后按业务规则做判断即可实现权限控制。
内容的提问来源于stack exchange,提问作者Rammboss
相关产品推荐
相关产品推荐

