防止活动上线时 微信openid 被伪造的问题
背景
前不久上线了一个 campaign 项目,一个 h5,用户可以在微信中通过网页授权的方式登录,然后用微信 openid 作为唯一标识符进行签到和抽奖的操作。
结果后期出现了很多脏数据来冒领抽奖的操作,这些脏数据的出现是因为 openid被伪造从而顺利入库。
解决问题的思路就是不让 openid 伪造,即采用 openid加密的方法。
流程图
采用对称加密
1、加密的对策是:微信授权的时候,后端回调给前端的 openid 加密;调用 api 的时候,都统一把加密后的 openid 传给后端,后端先做解密操作,然后再进行剩下的业务逻辑
2、因为 campaign 服务器同时负责加密和解密,可采用对称加密算法,这里我们选用更先进的 AES 加密算法
加密工具函数的代码如下:
function encrypt($string, $operation, $key = '')
{
$key = md5($key);
$key_length = strlen($key);
$string = $operation == 'D' ? base64_decode($string) : substr(md5($string . $key), 0, 8) . $string;
$string_length = strlen($string);
$rndkey = $box = array();
$result = '';
for ($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($key[$i % $key_length]);
$box[$i] = $i;
}
for ($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for ($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if ($operation == 'D') {
if (substr($result, 0, 8) == substr(md5(substr($result, 8) . $key), 0, 8)) {
return substr($result, 8);
} else {
return '';
}
} else {
return str_replace('=', '', base64_encode($result));
}
}
function encrypt_string($str)
{
$key = 'test';
return encrypt($str, 'E', $key); //加密
}
function decode_string($str)
{
$key = 'test';
return encrypt($str, 'D', $key); //解密
}