zoukankan      html  css  js  c++  java
  • 防止活动上线时 微信openid 被伪造的解决办法

    背景

    前不久上线了一个 campaign 项目,一个 h5,后端为php,用户可以在微信中通过网页授权的方式登录,然后用微信 openid 作为唯一标识符进行签到和抽奖的操作。

    结果后期出现了很多脏数据来冒领抽奖的操作,这些脏数据的出现是因为 openid 被伪造从而顺利入库。

    方法

    解决问题的思路就是不让 openid 伪造,有两种办法:

    方法一、每次获取 openid 参数时,调用微信公众平台的“获取用户基本信息”的接口

    方法二、采用 openid 加密的方法

    结论:方法一这个接口官方有调用频率的限制,所以我们采用方法二

    改造后的业务流程图

    这里需要改造两块代码:

    1、微信授权接口
    2、campagin api接口

    采用对称加密

    如上图所示:

    1、加密的对策是:微信授权的时候,后端把回调给前端的 openid 进行加密;调用 api 的时候,前端再把授权得到的加密后的 openid 传给后端,后端先做解密操作,然后再进行剩下的业务逻辑,如果解密操作失败,则认定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'; //这里的$key是密钥,请自行定义
        return encrypt($str, 'E', $key); //加密
    }
    
    function decode_string($str)
    {
        $key = 'test'; //这里的$key是密钥,请自行定义
        return encrypt($str, 'D', $key); //解密
    }
    
    

    调用:

    
    $openid_param = encrypt_string($openid_param);
    
    $openid_param = decode_string($openid_param);
    //如果$openid_param === false,则openid非法!
    
    
  • 相关阅读:
    選定下拉列表的方法
    JAVA学习路线
    封装
    重写(Overriding)
    java内存泄露
    学习实例.文章管理.文章类.Article.java
    方法重载
    学习实例.文章管理.分页查询类.Page.java
    学习实例.文章管理.目标与经验总结
    Java多线程1
  • 原文地址:https://www.cnblogs.com/xjnotxj/p/9289528.html
Copyright © 2011-2022 走看看