php 参数排序 计算sign_PHP API权限设计总结-系统sign验证规则

e1e361918bb186d3d3f3d01069da269e.png

网络安全越来越发达的今天, 系统安全是每一位开发者都需要考虑的问题, 比如用户注册, 如果提交的数据不做安全验证, 那么有些人或许会提交一堆的垃圾数据,久而久之你的数据库中的僵死数据会非常的多,影响正常数据的查询效率,同时你的系统也许就在某一天over了。所以安全一直都是我们工作考虑的重点。那么一般都会对提交的数据做安全的验证 比如通用的sign加密验证, sign 究竟是怎么个验证方法呢?

1.    首先是数据库api, 表结构的设计取决于自己的情况, 最基本的设计:

字段

type

Is null

Auto_increment

comment

id

Int(11)

not

自增id

Api_name

Varchar(25)

Not null

应用的名称

key

Varchar(32)

Not null

应用的key

secret

Varchar(32)

Not null

应用的密钥

2.    上面还没有提到sign究竟是怎么的回事儿呢?

第二步就是生成自己的sign, 每次提交的数据都要加上sign提交给后台。

Sign的算法一般都是采用对提交的数据进行排序后+secret后MD5

$key = "c4ca4238a0b923820dcc509a6f75849b";

$secret = "28c8edde3d61a0411511d3b1866f0636";

如:

$data = array(

'username' => 'sex' => '男',

'age' => '12',

'addr' => '北京市海淀区'

);

// 传递的参数中必须有 key, sign, timestamp

$postData = array(

"key" => $key,

"timestamp" => time()

);

// 一般情况提交到后台的数据在除了要提交的信息还要加上一些验证的数据 ($postData就是这样的数据)

// 将用户提交的数据和必须的参数一起排序(正序或者是倒序都可以, 子要保证验证的算法和加密的算法一致即可)

// 获取sign

function getSign($secret, $data){

// 对数组的值按key排序

ksort($data);

// 生成url的形式

$params = http_build_query($data);

// 生成sign

$sign = md5($params.$secret);

return $sign;

}

//将用户的数据和默认的数据合并

$psotData = array_merge($postData, $data);

// 发送的数据中吧sign带上

$psotData[‘sign’] = getSign($secret, $data);

// 数据组合好后可以吧数据发送到后台

3.     第三步就是在服务器端吧得到的数据进行验证处理.

对必须的参数进行验证:

1)   .  通过key在api的数据库中查找是否存在secret的值,没有则验证失败

2)   .  对传递过来的数据中验证sign参数是否存在, 不存在, 验证失败。

3)   .  对时间’timestamp’参数进行验证,大于10分钟的数据验证失败。

4)   、对出去sign的所有参数进行验证, 生成的sign和传递过来的sign参数是否一致, 不一致验证失败。

5)   . 如果上面的有验证通过后就可以执行下面的逻辑代码.

/**

* 验证sign是否合法

* @param [type] $secret [description]

* @param [type] $data [description]

* @return [type] [description]

*/

function verifySign($secret, $data){

// 验证参数中是否有签名

if (!isset($data['sign']) || !$data['sign']) {

echo '发送的数据签名不存在';

die();

}

if (!isset($data['timestamp']) || !$data['timestamp']) {

echo '发送的数据参数不合法';

die();

}

// 验证请求, 10分钟失效

if (time() - $data['timestamp'] > 600) {

echo '验证失效, 请重新发送请求';

die();

}

$sign = $data['sign'];

unset($data['sign']);

ksort($data);

$params = http_build_query($data);

// $secret是通过key在api的数据库中查询得到

$sign2 = md5($params.$secret);

if ($sign == $sign2) {

die('验证通过');

}else{

die('请求不合法');

}

}

receive.php

// 获取post的数组

$key = "c4ca4238a0b923820dcc509a6f75849b";

// $secret 是存储在数据库中, 可以根据传递过来的key在数据中的查询到secretZ12QAZ12

$secret = "28c8edde3d61a0411511d3b1866f0636";

$data = $_POST;

verifySign($secret, $data);

/**

* 验证sign是否合法

* @param [type] $secret [description]

* @param [type] $data [description]

* @return [type] [description]

*/

function verifySign($secret, $data)

{

// 验证参数中是否有签名

if (!isset($data['sign']) || !$data['sign']) {

echo '发送的数据签名不存在';

die();

}

if (!isset($data['timestamp']) || !$data['timestamp']) {

echo '发送的数据参数不合法';

die();

}

// 验证请求, 10分钟失效

if (time() - $data['timestamp'] > 600) {

echo '验证失效, 请重新发送请求';

die();

}

$sign = $data['sign'];

unset($data['sign']);

ksort($data);

$params = http_build_query($data);

$sign2 = md5($params.$secret);

if ($sign == $sign2) {

die('验证通过');

}else{

die('请求不合法');

}

}

?>

request.php

$key = "c4ca4238a0b923820dcc509a6f75849b";

$secret = "28c8edde3d61a0411511d3b1866f0636";

$data = array(

'username' => '[email protected]',

'sex' => '男',

'age' => '12',

'addr' => '北京市海淀区'

);

// 传递的参数中必须有 key, sign, timestamp

$postData = array(

"key" => $key,

"timestamp" => time()

);

$psotData = array_merge($postData, $data);

$sign = getSign($secret, $psotData);

$postData['sign'] = $sign;

// 获取sign

function getSign($secret, $data)

{

// 对数组的值按key排序

ksort($data);

// 生成url的形式

$params = http_build_query($data);

// 生成sign

$sign = md5($params.$secret);

return $sign;

}

$postData = array_merge($postData, $data);

request($postData);

/**

* 发送服务器的数据

* @param [type] $postData [description]

* @return [type] [description]

*/

function request($postData)

{

$curl = curl_init('http://host/receive.php');

curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($curl, CURLOPT_POST, TRUE);

curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);

$info = curl_exec($curl);

curl_close($curl);

print_r($info);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
转python写法:#!/bin/sh time_stamp=`date +%s` function CheckStop() { if [ $? -ne 0 ]; then echo "execute fail, error on line_no:"$1" exit!!!" exit fi } function GenEcdsaKey() { ec_param_file_path="/tmp/ec_param.pem."$time_stamp openssl ecparam -out $ec_param_file_path -name prime256v1 -genkey CheckStop $LINENO openssl genpkey -paramfile $ec_param_file_path -out $1 CheckStop $LINENO openssl pkey -in $1 -inform PEM -out $2 -outform PEM -pubout CheckStop $LINENO rm $ec_param_file_path echo "gen_ecdsa_key succ prikey_path:"$1" pubkey_path:"$2 } function GenEcdsaSign() { ec_sign_info_file="/tmp/ec_sign_info_file."$time_stamp ec_sign_info_sha256="/tmp/ec_sign_info_sha256."$time_stamp ec_binary_sign_file="/tmp/ec_binary_sign_file."$time_stamp echo -n "$1"_"$2" > $ec_sign_info_file openssl dgst -sha256 -binary -out $ec_sign_info_sha256 $ec_sign_info_file CheckStop $LINENO openssl pkeyutl -sign -in $ec_sign_info_sha256 -out $ec_binary_sign_file -inkey $3 -keyform PEM CheckStop $LINENO openssl base64 -e -in $ec_binary_sign_file -out $4 CheckStop $LINENO rm $ec_sign_info_file $ec_sign_info_sha256 $ec_binary_sign_file echo "gen_ecdsa_sign succ sign_file_path:"$4 } function VerifyEcdsaSign() { ec_sign_info_file="/tmp/ec_sign_info_file."$time_stamp ec_sign_info_sha256="/tmp/ec_sign_info_sha256."$time_stamp ec_binary_sign_file="/tmp/ec_binary_sign_file."$time_stamp echo -n "$1"_"$2" > $ec_sign_info_file openssl dgst -sha256 -binary -out $ec_sign_info_sha256 $ec_sign_info_file CheckStop $LINENO openssl base64 -d -in $4 -out $ec_binary_sign_file CheckStop $LINENO openssl pkeyutl -verify -in $ec_sign_info_sha256 -sigfile $ec_binary_sign_file -pubin -inkey $3 -keyform PEM rm $ec_sign_info_file $ec_sign_info_sha256 $ec_binary_sign_file } function Usage() { echo "Usage:" echo "mmiot_ecdsa_sign.sh gen_ecdsa_key <private_key_file_path> <public_key_file_path>" echo "mmiot_ecdsa_sign.sh gen_ecdsa_sign <product_id> <sn> <private_
05-31
以下是转换后的 Python 代码: ```python #!/usr/bin/env python import os import subprocess import base64 time_stamp = str(int(time.time())) def check_stop(line_no, ret): if ret != 0: print("execute fail, error on line_no: ", line_no, " exit!!!") exit() def gen_ecdsa_key(private_key_file_path, public_key_file_path): ec_param_file_path = "/tmp/ec_param.pem." + time_stamp ret = subprocess.call(["openssl", "ecparam", "-out", ec_param_file_path, "-name", "prime256v1", "-genkey"]) check_stop(sys._getframe().f_lineno, ret) ret = subprocess.call(["openssl", "genpkey", "-paramfile", ec_param_file_path, "-out", private_key_file_path]) check_stop(sys._getframe().f_lineno, ret) ret = subprocess.call(["openssl", "pkey", "-in", private_key_file_path, "-inform", "PEM", "-out", public_key_file_path, "-outform", "PEM", "-pubout"]) check_stop(sys._getframe().f_lineno, ret) os.remove(ec_param_file_path) print("gen_ecdsa_key succ prikey_path:", private_key_file_path, " pubkey_path:", public_key_file_path) def gen_ecdsa_sign(product_id, sn, private_key_file_path, sign_file_path): ec_sign_info_file = "/tmp/ec_sign_info_file." + time_stamp ec_sign_info_sha256 = "/tmp/ec_sign_info_sha256." + time_stamp ec_binary_sign_file = "/tmp/ec_binary_sign_file." + time_stamp with open(ec_sign_info_file, 'w') as f: f.write(product_id + "_" + sn) ret = subprocess.call(["openssl", "dgst", "-sha256", "-binary", "-out", ec_sign_info_sha256, ec_sign_info_file]) check_stop(sys._getframe().f_lineno, ret) ret = subprocess.call(["openssl", "pkeyutl", "-sign", "-in", ec_sign_info_sha256, "-out", ec_binary_sign_file, "-inkey", private_key_file_path, "-keyform", "PEM"]) check_stop(sys._getframe().f_lineno, ret) with open(ec_binary_sign_file, 'rb') as f: sign_binary = f.read() sign_base64 = base64.b64encode(sign_binary).decode() with open(sign_file_path, 'w') as f: f.write(sign_base64) os.remove(ec_sign_info_file) os.remove(ec_sign_info_sha256) os.remove(ec_binary_sign_file) print("gen_ecdsa_sign succ sign_file_path:", sign_file_path) def verify_ecdsa_sign(product_id, sn, public_key_file_path, sign_file_path): ec_sign_info_file = "/tmp/ec_sign_info_file." + time_stamp ec_sign_info_sha256 = "/tmp/ec_sign_info_sha256." + time_stamp ec_binary_sign_file = "/tmp/ec_binary_sign_file." + time_stamp with open(ec_sign_info_file, 'w') as f: f.write(product_id + "_" + sn) ret = subprocess.call(["openssl", "dgst", "-sha256", "-binary", "-out", ec_sign_info_sha256, ec_sign_info_file]) check_stop(sys._getframe().f_lineno, ret) with open(sign_file_path, 'r') as f: sign_base64 = f.read() sign_binary = base64.b64decode(sign_base64) with open(ec_binary_sign_file, 'wb') as f: f.write(sign_binary) ret = subprocess.call(["openssl", "pkeyutl", "-verify", "-in", ec_sign_info_sha256, "-sigfile", ec_binary_sign_file, "-pubin", "-inkey", public_key_file_path, "-keyform", "PEM"]) os.remove(ec_sign_info_file) os.remove(ec_sign_info_sha256) os.remove(ec_binary_sign_file) print("verify_ecdsa_sign result:", "succ" if ret == 0 else "fail") if len(sys.argv) < 2: print("Usage:") print("python mmiot_ecdsa_sign.py gen_ecdsa_key <private_key_file_path> <public_key_file_path>") print("python mmiot_ecdsa_sign.py gen_ecdsa_sign <product_id> <sn> <private_key_file_path> <sign_file_path>") print("python mmiot_ecdsa_sign.py verify_ecdsa_sign <product_id> <sn> <public_key_file_path> <sign_file_path>") exit() if sys.argv[1] == "gen_ecdsa_key": gen_ecdsa_key(sys.argv[2], sys.argv[3]) elif sys.argv[1] == "gen_ecdsa_sign": gen_ecdsa_sign(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) elif sys.argv[1] == "verify_ecdsa_sign": verify_ecdsa_sign(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) else: print("Usage:") print("python mmiot_ecdsa_sign.py gen_ecdsa_key <private_key_file_path> <public_key_file_path>") print("python mmiot_ecdsa_sign.py gen_ecdsa_sign <product_id> <sn> <private_key_file_path> <sign_file_path>") print("python mmiot_ecdsa_sign.py verify_ecdsa_sign <product_id> <sn> <public_key_file_path> <sign_file_path>") ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值