Ruby加密URL参数后,PHP端解密逻辑及加载位置咨询
解决方案:在中间处理脚本中解密并完成追踪
你需要在邮件客户端请求加密链接时,先通过一个中间PHP脚本解密出真实的追踪URL参数,然后直接在该脚本内完成数据库更新并返回像素——不需要跳转,这样就能保证邮件打开时的追踪逻辑正常执行,同时对用户完全透明。
具体步骤:
修改邮件中的加密链接格式
把原来的加密内容作为参数传给中间处理脚本,比如:http://your-domain.com/decrypt_track.php?data=3ISGSfzIiaAU+h2TwF0pNoKDKRenjKfRhehMMN3+OJw=(注意:如果加密字符串包含
+等特殊字符,最好提前用urlencode处理,避免参数解析错误)创建
decrypt_track.php中间脚本
这个脚本整合了解密、数据库更新、返回像素的完整逻辑,替代原来分散的文件分工:<?php require_once("./db_connection.php"); class StringDecrypt { function decrypt($string) { $encrypted_data = base64_decode($string); $key = base64_decode("bzFkaXF3a2Fka2ZqZzAxOGpna2RqYTkxOTQwMjUxMjM="); $iv = base64_decode("YWtqZ2tkbGFkamdrYWRzdw=="); // 兼容原有mcrypt实现(注意:mcrypt已被PHP7.2+弃用,建议看后面的替代方案) $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_data, MCRYPT_MODE_CBC, $iv); // 修正填充移除逻辑,原rtrim不够准确 $pad = ord($result[strlen($result) - 1]); return substr($result, 0, -$pad); } } // 1. 获取加密参数 $encryptedData = isset($_GET['data']) ? $_GET['data'] : ''; if (empty($encryptedData)) { // 即使参数为空,也要返回空像素避免报错 header('Content-Type: image/gif'); $img = imagecreatefromgif("px.gif"); imagegif($img); imagedestroy($img); exit; } // 2. 解密并解析subid参数 $decrypter = new StringDecrypt(); $decryptedUrl = $decrypter->decrypt($encryptedData); parse_str(parse_url($decryptedUrl, PHP_URL_QUERY), $params); $subid = isset($params['subid']) ? intval($params['subid']) : 0; // 3. 更新数据库打开统计 if ($subid > 0) { $conn = new mysqli($servername, $username, $password, $db); if ($conn->connect_error) { // 数据库连接失败也不能中断像素返回 header('Content-Type: image/gif'); $img = imagecreatefromgif("px.gif"); imagegif($img); imagedestroy($img); $conn->close(); exit; } $conn->set_charset("utf8"); $stmt = $conn->prepare("UPDATE rcpt SET has_opens = has_opens + 1 WHERE id = ? "); $stmt->bind_param('i', $subid); $stmt->execute(); $stmt->close(); $conn->close(); } // 4. 返回1x1像素图片,让邮件客户端认为加载成功 header('Content-Type: image/gif'); $img = imagecreatefromgif("px.gif"); imagegif($img); imagedestroy($img); ?>(推荐)替换弃用的mcrypt为openssl
PHP7.2及以上版本已移除mcrypt扩展,建议把解密函数改成更稳定的openssl实现:function decrypt($string) { $encrypted_data = base64_decode($string); $key = base64_decode("bzFkaXF3a2Fka2ZqZzAxOGpna2RqYTkxOTQwMjUxMjM="); $iv = base64_decode("YWtqZ2tkbGFkamdrYWRzdw=="); // AES-256-CBC对应Ruby中的aes-256-cbc,块大小为128位 return openssl_decrypt($encrypted_data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); }
核心逻辑说明
邮件中的像素链接是由客户端直接发起请求的,客户端本身无法执行解密逻辑,所以必须让请求先经过我们的中间脚本:先解密拿到追踪参数,完成数据库统计,最后返回像素图片。这样既保证了链接的安全性,又能正常触发打开统计。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

