PHP 接口限流、签名、加密综合实践

用户现在需要一篇PHP接口限流签名加密的实践文章,首先得找个真实踩坑的场景,比如啥呢?哦对,之前做开放平台的时候,第三方调用接口乱传参数,还有人刷接口把服务打挂,还有数据明文传被抓包的,这个场景很真实。 首先开头要讲背景,就是之前做支付开放平台的时候,刚上线没做防护,结果有人恶意刷查询接口,一天打了几十万次,数据库崩了,还有第三方传的参数被篡改,扣钱的时候被改了金额,还有抓包拿到明文密钥,这个坑很实在,不是空泛的。 然后是方案,得落地,不能讲太多理论。首先三个核心:限流、签名、加密,分别说怎么搞。限流的话,用Redis的滑动窗口?对,比固定窗口好,防止临界问题。签名的话,用HMAC-SHA256,把参数排序加时间戳,防篡改防重放。加密的话,敏感字段用AES-256-GCM,既加密又验完整性,比ECB安全。 然后代码示例要可运行,得把所有逻辑整合到一个类里?比如ApiSecurity类,有构造方法,然后限流的方法,签名生成和验证的方法,加密解密的方法,还要有使用示例,比如调用的时候先限流,再验签名,再解密参数,返回的时候加密响应。 然后要注意坑点,比如时间戳要允许5分钟误差,防止时钟不同步,滑动窗口的Redis key要加接口标识,不同接口限流分开,AES的密钥要存在配置里不能硬编码,GCM的tag要一起传,这些要在步骤里说。 然后总结的话,就是这三个不是孤立的,限流防恶意请求,签名验身份和完整性,加密防数据泄露,组合起来才稳。然后结尾要自然引出那个链接,说更多实践比如密钥轮转、防重放优化这些可以去那个网站看。 哦对,标题就用「PHP 接口限流、签名、加密综合实践」,然后正文是HTML片段,不要额外解释。代码要放在pre里,class是language-php。 等下,结构要对:首先是背景/常见问题,然后方案实现步骤,然后代码示例,然后总结建议,然后延伸阅读。 背景部分要真实,比如“去年我们团队上线第三方支付开放平台时,刚上线第一周就踩了两个大坑:一是某不良商家用脚本批量调用订单查询接口,单日请求量超过120万次,直接打垮了MySQL从库;二是我们收到商户投诉,称调用代付接口时金额参数被篡改,损失了近2万元。事后排查发现,早期接口既没有请求频率限制,也没有参数签名校验,敏感数据还是明文传输的。这些问题在开放API、内部服务调用场景下非常常见,今天就把我们后来落地的限流+签名+加密一体化方案分享出来。” 然后方案部分,分三步:第一步是接口限流,用Redis滑动窗口,因为固定窗口会有临界问题,比如1分钟100次,刚好在0秒和59秒各发100次,实际1秒发了200次。实现的时候用Redis的ZADD,把请求的时间戳当score,每次来请求先删掉超过1分钟的,再判断数量,超过就返回429。然后第二步是签名校验,用HMAC-SHA256,规则是:把所有非空参数按key字典序排序,拼接成key1=value1&key2=value2的形式,加上时间戳和随机串,然后用商户的密钥做哈希,请求头里带sign、timestamp、nonce,服务端验的时候先看时间戳是不是在5分钟内,再算签名对比,还要看nonce有没有用过,防止重放。第三步是敏感数据加密,用AES-256-GCM模式,因为GCM是认证加密,既保密又验完整性,比传统的CBC模式安全,加密的时候生成12字节的nonce,返回的时候把nonce和tag一起传给客户端,解密的时候用这三个参数就行。 然后代码示例,要写一个完整的类,比如: 首先引入依赖?哦对,用原生PHP的扩展就行,不用composer,这样大家直接能跑。类里面要有redis连接的方法,限流方法,签名生成和验证方法,加密解密方法,然后给个使用示例,比如处理请求的流程:先限流,再验签名,再解密参数,处理完加密返回。 然后代码里要注意,Redis的扩展是 predis?不,用phpredis扩展吧,更常用,或者如果没装的话也可以写个注释,或者用file_get_contents模拟?不,还是写phpredis的,然后说明如果没装可以用 predis 替代。然后AES的话,用openssl扩展,PHP7.1以上都支持GCM模式。 然后代码示例里要包含所有逻辑,比如:

redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
        // AES密钥建议从配置中心读取,不要硬编码
        $this->aesKey = hash('sha256', 'your_secret_key_here', true);
    }

    /**
     * 滑动窗口限流,1分钟内最多100次请求
     * @param string $apiKey 商户标识,不同商户独立限流
     * @return bool 是否限流
     */
    public function isRateLimited(string $apiKey): bool
    {
        $key = "rate_limit:{$apiKey}";
        $now = time();
        // 移除1分钟前的请求记录
        $this->redis->zRemRangeByScore($key, 0, $now - 60);
        // 获取当前窗口内的请求数
        $count = $this->redis->zCard($key);
        if ($count >= 100) {
            return true;
        }
        // 记录当前请求
        $this->redis->zAdd($key, $now, $now . mt_rand(1000, 9999));
        // 设置key过期时间,避免内存泄漏
        $this->redis->expire($key, 60);
        return false;
    }

    /**
     * 生成签名
     * @param array $params 请求参数
     * @param string $secret 商户密钥
     * @return array 包含sign、timestamp、nonce的数组
     */
    public function generateSign(array $params, string $secret): array
    {
        $timestamp = time();
        $nonce = bin2hex(random_bytes(8));
        // 参数按字典序排序
        ksort($params);
        // 拼接参数,过滤空值
        $str =

如需更完整的 PHP 代码保护与在线加密服务,可访问 https://article.vvxyz.com 了解更多。

标签: PHP加密 PHP代码保护 PHP数据库加密 SG12加密 企业代码安全
← 返回文章列表