PHP5.6项目调用PHP7的Sodium扩展实现加解密方案咨询
可行实现方案
针对你的场景,include会在当前PHP5.6进程内执行代码(无法触发PHP7环境),file_get_contents仅读取文件内容而非执行PHP逻辑,所以需要用以下几种方式实现跨版本调用:
1. 本地HTTP请求调用.php7接口
利用Web服务器对.php7文件的解析规则,在PHP5.6代码中通过HTTP请求调用对应的加解密接口,传递参数并获取结果。推荐用cURL(兼容性更好):
// PHP5.6的.php文件中代码 function call_sodium_api($action, $data) { $url = 'https://mydoman/encode/v2/test.php7'; $post_data = http_build_query([ 'action' => $action, // 比如encrypt/decrypt 'data' => $data ]); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 本地请求可添加CURLOPT_FOLLOWLOCATION等优化参数 $result = curl_exec($ch); curl_close($ch); return json_decode($result, true); // 假设接口返回JSON格式结果 } // 调用示例 $encrypted = call_sodium_api('encrypt', '需要加密的内容'); $decrypted = call_sodium_api('decrypt', $encrypted['ciphertext']);
注意事项:
- 确保Web服务器能正常将.php7文件解析到PHP7环境
- 接口需做好参数校验和权限控制,避免非法调用
- 本地场景可改用
http://localhost/...减少网络开销
2. 命令行调用PHP7解释器执行.php7文件
如果服务器上有PHP7的CLI二进制文件(比如路径为/usr/bin/php7),可以通过PHP执行函数调用该解释器运行.php7文件:
首先编写独立的.php7处理脚本(比如sodium_handler.php7):
// sodium_handler.php7 代码 if ($argc < 3) { exit(json_encode(['error' => '参数不足'])); } $action = $argv[1]; $data = json_decode(base64_decode($argv[2]), true); $result = []; switch ($action) { case 'encrypt': $key = sodium_crypto_secretbox_keygen(); $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $ciphertext = sodium_crypto_secretbox($data['plaintext'], $nonce, $key); $result = [ 'ciphertext' => base64_encode($ciphertext), 'nonce' => base64_encode($nonce), 'key' => base64_encode($key) // 实际场景请妥善存储密钥,勿直接返回 ]; break; case 'decrypt': $ciphertext = base64_decode($data['ciphertext']); $nonce = base64_decode($data['nonce']); $key = base64_decode($data['key']); $result = ['plaintext' => sodium_crypto_secretbox_open($ciphertext, $nonce, $key)]; break; default: $result = ['error' => '不支持的操作']; } echo json_encode($result);
然后在PHP5.6的.php文件中调用:
// PHP5.6代码 function call_sodium_cli($action, $data) { $php7_path = '/usr/bin/php7'; // 根据实际路径调整 $handler_path = '/path/to/sodium_handler.php7'; // 脚本绝对路径 // 编码数据避免命令行参数解析问题,用escapeshellarg防止注入 $encoded_data = base64_encode(json_encode($data)); $command = "$php7_path $handler_path " . escapeshellarg($action) . " " . escapeshellarg($encoded_data); $output = shell_exec($command); return json_decode($output, true); } // 调用示例 $encrypt_params = ['plaintext' => '需要加密的内容']; $encrypted = call_sodium_cli('encrypt', $encrypt_params); $decrypted = call_sodium_cli('decrypt', $encrypted);
注意事项:
- 确认PHP7 CLI路径正确,且当前PHP5.6进程有执行权限
- 必须用
escapeshellarg()处理参数,杜绝命令注入风险 - 敏感数据(如密钥)不要通过命令行参数传递,可改用临时文件或环境变量
3. 本地Socket服务(高并发场景)
如果需要频繁调用且对性能要求高,可搭建PHP7本地Socket服务,PHP5.6通过Socket发送请求:
PHP7 Socket服务端(sodium_socket_server.php7)
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0); socket_bind($socket, '/tmp/sodium.sock'); socket_listen($socket); while (true) { $client = socket_accept($socket); $request = socket_read($client, 1024); $params = json_decode($request, true); $result = []; if (isset($params['action'], $params['data'])) { switch ($params['action']) { case 'encrypt': $key = sodium_crypto_secretbox_keygen(); $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $ciphertext = sodium_crypto_secretbox($params['data'], $nonce, $key); $result = [ 'ciphertext' => base64_encode($ciphertext), 'nonce' => base64_encode($nonce), 'key' => base64_encode($key) ]; break; case 'decrypt': $ciphertext = base64_decode($params['data']['ciphertext']); $nonce = base64_decode($params['data']['nonce']); $key = base64_decode($params['data']['key']); $result = ['plaintext' => sodium_crypto_secretbox_open($ciphertext, $nonce, $key)]; break; } } else { $result = ['error' => '无效请求']; } socket_write($client, json_encode($result)); socket_close($client); }
PHP5.6客户端代码
function call_sodium_socket($action, $data) { $socket = socket_create(AF_UNIX, SOCK_STREAM, 0); socket_connect($socket, '/tmp/sodium.sock'); $request = json_encode(['action' => $action, 'data' => $data]); socket_write($socket, $request); $response = socket_read($socket, 1024); socket_close($socket); return json_decode($response, true); } // 调用示例 $encrypted = call_sodium_socket('encrypt', '需要加密的内容');
注意事项:
- 确保/tmp目录有读写权限,Socket文件权限配置正确
- 服务端需后台运行(比如
nohup php7 sodium_socket_server.php7 &) - 需处理Socket连接异常和超时问题
内容的提问来源于stack exchange,提问作者New Laravel Bugs
相关产品推荐
相关产品推荐

