Widget与Analytics嵌入脚本的认证机制及PHP可信域名验证咨询
防止Widget/Analytics脚本被盗用的方案 & PHP域名验证方法
一、防止脚本被未授权网站滥用的核心方案
客户端的任何信息都能被篡改,所以必须客户端校验+后端强验证结合,以下是实际可用的手段:
- 绑定公钥到授权域名:用户配置账号时,要求填写允许使用该Widget的域名列表(比如
example.com、blog.example.com),后端将公钥和域名列表关联存储。当Widget脚本加载时,前端先获取当前页面的window.location.host做一层客户端校验(不匹配就直接停止渲染);同时前端向后端请求核心数据时,带上当前域名和公钥,后端校验该公钥对应的允许域名列表里是否包含这个域名,不匹配就拒绝返回数据。 - 请求签名验证:前端Widget用公钥+当前域名+时间戳,通过HMAC算法生成签名(比如
HMAC-SHA256),向后端请求时带上公钥、域名、时间戳和签名。后端用对应私钥+存储的允许域名+时间戳重新计算签名,对比一致才通过验证。时间戳还能防止重放攻击(比如限制请求在5分钟内有效)。 - Referer头校验(辅助防线):后端接收Widget的请求时,先检查
Referer头的域名是否在授权列表里。虽然Referer可以被伪造,但作为低成本的第一道过滤,能挡住大部分非技术型盗用。 - 动态生成嵌入代码:不给用户固定的公钥脚本,而是每次生成嵌入代码时,带上和用户域名绑定的临时token,或者让用户通过后端接口动态获取嵌入脚本,脚本里的标识和当前请求的域名绑定,过期失效。
二、PHP中验证请求来源域名的方法
PHP里没有绝对安全的单一步骤,必须结合多种手段:
1. 解析并校验Referer头
// 先检查Referer是否存在 if (!isset($_SERVER['HTTP_REFERER'])) { http_response_code(403); exit('Unauthorized'); } // 解析Referer获取域名 $refererInfo = parse_url($_SERVER['HTTP_REFERER']); if (!$refererInfo || !isset($refererInfo['host'])) { http_response_code(403); exit('Invalid referer'); } // 允许的域名列表(从数据库或配置文件读取) $allowedDomains = ['example.com', 'blog.example.com']; // 校验域名是否在允许列表 if (!in_array($refererInfo['host'], $allowedDomains)) { http_response_code(403); exit('Domain not allowed'); }
⚠️ 注意:HTTP_REFERER可能为空(比如浏览器隐私设置禁用、直接访问接口),所以不能单独依赖这个,必须和签名验证结合。
2. 结合签名验证(安全级别更高)
假设前端发送的请求参数包含public_key、domain、timestamp、signature:
// 从请求中获取参数 $publicKey = $_GET['public_key'] ?? ''; $requestDomain = $_GET['domain'] ?? ''; $timestamp = $_GET['timestamp'] ?? ''; $signature = $_GET['signature'] ?? ''; // 1. 检查时间戳是否有效(防止重放攻击,限制5分钟内) if (time() - intval($timestamp) > 300) { http_response_code(403); exit('Request expired'); } // 2. 从数据库获取该公钥对应的私钥和允许域名列表(示例用模拟数据) $storedData = [ 'private_key' => 'your-stored-private-key', 'allowed_domains' => ['example.com', 'blog.example.com'] ]; // 3. 校验请求域名是否在允许列表 if (!in_array($requestDomain, $storedData['allowed_domains'])) { http_response_code(403); exit('Domain not allowed'); } // 4. 重新计算签名并对比 $dataToSign = $publicKey . $requestDomain . $timestamp; $calculatedSignature = hash_hmac('sha256', $dataToSign, $storedData['private_key']); if ($calculatedSignature !== $signature) { http_response_code(403); exit('Invalid signature'); } // 验证通过,处理请求 echo 'Valid request';
3. 注意事项
- 永远不要信任客户端传来的域名参数,必须从请求头或签名里间接验证。
- 允许的域名建议用精确匹配,或者支持通配符(比如
*.example.com),但通配符要注意校验逻辑(避免误匹配example.com.cn这类域名)。 - 私钥要妥善存储在后端,绝对不能暴露给前端。
内容的提问来源于stack exchange,提问作者RDU
相关产品推荐
相关产品推荐

