[PHP] 接口请求校验的原理

通过llama.cpp与羊驼聊天的网页界面- 详解 Serge 的启动使用

 

具体的校验步骤可以自定义,下面是比较直观的一种形式:

 

1. 客户端:请求参数带上时间,进行首字母排序,连接私钥后,取得加密结果;

客户端请求时带上这个加密结果作为sign参数。

2. 服务端:对sign参数进行校验(过程同上),如果正确且在有效期内,则通过。

 

示例程序:

<?php
/**
 * SignCheck : session key 对称式 加密校验.
 *
 * 注:公私钥模式可以避免私钥被窃取.
 *
 * @farwish.com
 */

// Client:

$time = time();
$url = "b=v1&a=v2&c=v3&time={$time}";
// Client和Server通用私钥.
$uuid = 'b9514c52-5363-4364-b73f-a2ec93ae6b34';

function getSign($url, $uuid, $encode = true)
{
    parse_str( $url, $arr );

    if (! $encode ) { 
        unset($arr['sign']);
    }   

    // 1. 参数按首字母排序
    ksort($arr, SORT_REGULAR);

    $str = http_build_query($arr);

    // 2. 参数字符串拼接私钥(TODO自定义)
    $new_str = $str . $uuid;

    // 3. 生成新sign(TODO自定义)
    $sign = openssl_encrypt($new_str, 'AES-128-CBC', $uuid, OPENSSL_RAW_DATA, substr($uuid, 0, 16));
    return md5($sign);
}

// 4. 参数拼接sign进行请求
$client_sign = getSign($url, $uuid);
$request_url = $url . "&sign={$client_sign}";

// Server:

// 去除sign重新校验,并检查time有效期
$server_sign = getSign($request_url, $uuid, false);

//sleep(4);

if ( ($client_sign == $server_sign) &&
    ( (time() - $time) < 5 )
) {
    echo "{$server_sign} 有效,且在有效期内.\n";
} else {
    echo "无效请求.\n";
}

Source:https://github.com/farwish/php-lab/blob/master/lab/SignCheck.php

Bound in Library:https://github.com/farwish/alcon/blob/master/src/Supports/Helper.php

Tests:https://github.com/farwish/alcon/blob/master/tests/Supports/HelperTest.php

 

小结:这种校验方式,只有完全知道了校验算法的客户端才能模拟合法请求,防止数据篡改,相对安全。

如果需要验证用户登录的情况,可以使用JWT的方式。

 


Link:http://www.cnblogs.com/farwish/p/6700518.html

posted on 2017-04-12 18:02  ercom  阅读(2000)  评论(0编辑  收藏  举报