phpEnv是一款集成了PHP、MySQL、Nginx等多种开发组件的本地环境管理工具,很多开发者会用它来搭建PHP项目的开发环境。如果需要为项目引入云原生身份管理能力,Zitadel是一个不错的选择,它支持多租户、OAuth2、OpenID Connect等主流身份协议,适配各类开发场景。

前置准备
在phpEnv中部署Zitadel需要先确认环境满足以下要求:
- phpEnv版本不低于8.0,已开启Docker扩展功能
- 本地已安装Docker Desktop,并且处于运行状态
- 预留至少2GB的磁盘空间用于存储Zitadel相关数据
安装Docker扩展并配置
phpEnv默认可能没有开启Docker支持,需要先手动开启该扩展:
- 打开phpEnv管理面板,点击左侧菜单的
扩展管理选项 - 在扩展列表中找到
Docker扩展,点击启用按钮,等待扩展安装完成 - 启用完成后,在phpEnv面板中点击
Docker菜单,确认可以正常显示Docker容器列表
部署Zitadel服务
Zitadel官方提供了Docker镜像,我们可以通过phpEnv的Docker管理功能快速拉取并启动服务:
拉取Zitadel镜像
打开phpEnv的Docker终端,执行以下命令拉取最新的Zitadel镜像:
# 拉取Zitadel官方镜像 docker pull zitadel/zitadel:latest
启动Zitadel容器
镜像拉取完成后,执行以下命令启动Zitadel服务,同时映射端口和挂载数据目录:
# 启动Zitadel容器 docker run -d --name zitadel -p 8080:8080 -p 8081:8081 -v /path/to/phpEnv/data/zitadel:/data zitadel/zitadel:latest start --masterKey "master-key-123456" --database.postgres.hosts "host.docker.internal:5432" --database.postgres.user "postgres" --database.postgres.password "postgres" --database.postgres.dbname "zitadel"
命令中的参数说明:
-p 8080:8080:映射Zitadel的HTTP服务端口-p 8081:8081:映射Zitadel的gRPC服务端口-v /path/to/phpEnv/data/zitadel:/data:将Zitadel的数据目录挂载到phpEnv的数据目录下,避免容器删除后数据丢失,需要将/path/to/phpEnv替换为你本地phpEnv的实际安装路径--masterKey:设置Zitadel的主密钥,生产环境需要替换为更复杂的字符串- 数据库相关参数:这里使用phpEnv自带的PostgreSQL服务,host.docker.internal是Docker访问本地服务的固定地址,账号密码和数据库名需要根据你phpEnv中PostgreSQL的实际配置调整
初始化Zitadel实例
容器启动后,打开浏览器访问http://127.0.0.1:8080,会进入Zitadel的初始化页面:
- 设置管理员邮箱和密码,这是Zitadel的超级管理员账号
- 选择默认的语言和时区,建议选择中文和Asia/Shanghai
- 确认实例初始化信息,点击
创建实例按钮,等待初始化完成
验证部署结果
初始化完成后,使用刚才设置的管理员账号登录Zitadel管理后台,如果可以正常进入控制台,说明部署成功。我们可以在控制台中创建应用、配置OAuth2客户端,然后在phpEnv中的PHP项目里调用Zitadel的接口实现身份认证功能。
常见问题排查
- 如果容器启动后无法访问8080端口,先检查phpEnv的Docker是否正常连接,再查看容器日志,执行
docker logs zitadel查看报错信息 - 如果连接PostgreSQL失败,确认phpEnv中的PostgreSQL服务已启动,并且允许远程连接,默认phpEnv的PostgreSQL已经开启了本地连接权限
- 如果数据挂载失败,检查本地挂载目录是否存在,并且phpEnv有该目录的读写权限
PHP项目集成示例
部署完成后,我们可以在PHP项目中调用Zitadel的OpenID Connect接口实现用户登录,以下是简单的示例代码:
<?php
// Zitadel配置信息
$zitadelUrl = 'http://127.0.0.1:8080';
$clientId = 'your-client-id'; // 在Zitadel控制台创建应用后获取
$clientSecret = 'your-client-secret'; // 应用对应的密钥
$redirectUri = 'http://127.0.0.1/test/callback.php';
// 跳转Zitadel登录页
if (!isset($_GET['code'])) {
$authUrl = $zitadelUrl . '/oauth/v2/authorize?client_id=' . $clientId . '&redirect_uri=' . urlencode($redirectUri) . '&response_type=code&scope=openid profile email';
header('Location: ' . $authUrl);
exit;
}
// 获取授权码后换取用户信息
$code = $_GET['code'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $zitadelUrl . '/oauth/v2/token');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => $redirectUri,
'client_id' => $clientId,
'client_secret' => $clientSecret
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$tokenData = json_decode($response, true);
$accessToken = $tokenData['access_token'];
// 获取用户信息
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $zitadelUrl . '/oidc/v1/userinfo');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $accessToken]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$userInfo = curl_exec($ch);
curl_close($ch);
echo '用户信息:' . $userInfo;
?>
以上代码实现了基础的Zitadel登录集成流程,实际项目中可以根据需求调整权限范围和用户信息处理逻辑。