在多站点架构下,PHP实现共用密钥可以简化跨站点的身份校验、数据加密流程,避免每个站点单独维护密钥带来的管理成本和安全隐患。实现多站点共用密钥需要兼顾存储安全性、访问便利性和传输可靠性。

PHP实现多站点共用密钥的核心方法
1. 统一密钥存储方案
最基础的方式是将共用密钥存储在独立的配置文件中,所有站点都读取该文件。为了避免密钥泄露,配置文件不要放在网站根目录下。
首先创建一个独立的密钥配置文件secret_key.php,放在站点根目录的上一级目录,比如路径为/data/config/secret_key.php,文件内容如下:
<?php
// 定义多站点共用的加密密钥
define('SHARED_SECRET_KEY', 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6');
// 定义密钥过期时间,单位秒
define('KEY_EXPIRE_TIME', 86400);
?>
然后在每个站点的入口文件中引入该配置,注意不同站点的路径需要根据实际部署调整:
<?php
// 引入共用密钥配置,路径根据实际部署修改
require_once '/data/config/secret_key.php';
// 验证密钥是否引入成功
if (!defined('SHARED_SECRET_KEY')) {
die('共用密钥加载失败');
}
echo '共用密钥加载成功';
?>
2. 基于环境变量的密钥共享
如果使用Docker或者服务器运维规范允许,可以将共用密钥配置为系统环境变量,所有站点的PHP进程都可以读取,避免密钥文件被直接访问的风险。
首先在服务器环境变量中配置密钥:
# 在服务器环境变量配置文件中添加 export PHP_SHARED_SECRET_KEY="a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
然后在PHP中读取环境变量:
<?php
// 读取环境变量中的共用密钥
$sharedKey = getenv('PHP_SHARED_SECRET_KEY');
if (empty($sharedKey)) {
die('未获取到共用密钥环境变量');
}
echo '从环境变量读取到的共用密钥为:' . substr($sharedKey, 0, 8) . '****';
?>
3. 共用密钥的实际使用示例
多站点共用密钥最常见的场景是生成跨站点校验的Token,以下是一个使用共用密钥生成和校验Token的示例:
<?php
require_once '/data/config/secret_key.php';
/**
* 使用共用密钥生成校验Token
* @param array $data 需要携带的数据
* @return string 生成的Token
*/
function generateSharedToken($data) {
$data['expire'] = time() + KEY_EXPIRE_TIME;
// 将数据序列化为字符串
$dataStr = json_encode($data);
// 使用共用密钥生成签名
$signature = hash_hmac('sha256', $dataStr, SHARED_SECRET_KEY);
// 拼接数据和签名生成Token
return base64_encode($dataStr . '|' . $signature);
}
/**
* 校验跨站点传递的Token
* @param string $token 待校验的Token
* @return array|false 校验成功返回数据,失败返回false
*/
function verifySharedToken($token) {
$decodeToken = base64_decode($token);
if (strpos($decodeToken, '|') === false) {
return false;
}
list($dataStr, $signature) = explode('|', $decodeToken, 2);
// 重新计算签名对比
$newSignature = hash_hmac('sha256', $dataStr, SHARED_SECRET_KEY);
if (!hash_equals($newSignature, $signature)) {
return false;
}
$data = json_decode($dataStr, true);
// 校验Token是否过期
if (isset($data['expire']) && $data['expire'] < time()) {
return false;
}
return $data;
}
// 生成Token示例
$testData = ['user_id' => 1001, 'site_id' => 1];
$token = generateSharedToken($testData);
echo '生成的跨站点Token:' . $token . '<br/>';
// 校验Token示例
$verifyResult = verifySharedToken($token);
if ($verifyResult !== false) {
echo 'Token校验成功,用户ID:' . $verifyResult['user_id'];
} else {
echo 'Token校验失败';
}
?>
PHP多站点密钥共享的注意事项
- 密钥存储位置不能放在网站可访问的目录下,避免被直接下载泄露,建议放在服务器非web目录或者使用环境变量存储。
- 密钥不要硬编码在PHP业务代码中,一旦代码泄露会直接导致密钥暴露,统一通过配置文件或者环境变量引入。
- 不同环境的共用密钥要区分,开发环境、测试环境、生产环境使用不同的密钥,避免测试密钥泄露影响生产环境安全。
- 跨站点传递密钥相关数据时,不要明文传输,建议通过HTTPS协议传输,避免在网络中被拦截获取。
- 定期轮换共用密钥,设置合理的密钥有效期,降低密钥泄露后的影响范围,轮换时做好新旧密钥的兼容过渡。
- 限制密钥的访问权限,配置文件或者环境变量只允许PHP进程运行的用户读取,其他用户无权访问。
常见问题解答
Q:多个站点部署在不同服务器上怎么共享密钥?
可以将密钥存储在高可用的配置中心如Consul、Etcd中,所有服务器上的PHP站点都从配置中心读取密钥,或者将密钥配置文件通过安全的方式同步到所有服务器的固定路径,保持内容一致。
Q:共用密钥泄露了怎么办?
立即生成新的共用密钥替换旧密钥,同时排查泄露原因,检查所有站点的日志是否有异常请求,确认没有数据被篡改或窃取后,完成密钥的更新。
多站点密钥共享的核心是平衡便利性和安全性,开发者需要根据实际部署场景选择合适的存储和读取方案,同时严格遵循安全规范,避免密钥泄露带来安全风险。