PHP 对参数签名

  • 对参数进行签名防止参数劫持
  • 加入timestamp, 防止DOS攻击(但这次没有实现这个功能,后续再实现)
     1 interface BaseToken
     2 {
     3 
     4     /**
     5      * @param params array|string 前端请求的参数
     6      * @param key string 秘钥
     7      * @return sign string
     8      */
     9     public function getSign($params, string $key);
    10 }
    11 
    12 class Token implements BaseToken
    13 {
    14 
    15     public $privateKey = 'thisisprivateKey!!';
    16 
    17     /**
    18      * 后端根据前端的参数生成的签名, 签名是防止参数劫持
    19      * 还可以判断timestamp,防止DOS攻击
    20      * @return sign
    21      */
    22     public function getSign($params, string $privateKey)
    23     {
    24         //有的接口可能需要判断timestamp,防止DOS攻击,判断是否传入了timestamp
    25         if(isset($params['timestamp'])){
    26             if(abs($params['timestamp']-time()) > 60*15){
    27                 return ['code'=>10001, 'msg'=>'timestamp失效,请重新发送请求'];
    28             }
    29         }
    30         $string = '';
    31         foreach ($params as $key => $value) {
    32             // firstly unset value of empty
    33             if(!$value){
    34                 unset($params[$key]);
    35             }
    36         }
    37         //参数名按ASCII吗从小到大排序(字典序)
    38         ksort($params);
    39         $str = '';
    40         foreach ($params as $key => $value) {
    41             //前端请求的参数里面是包含sign的,需要过滤。,timestamp 也参与签名.
    42             if($key != 'sign' && !is_array($value))
    43             $str .= $key.'='.$value.'&';
    44         }
    45         //拼接privateKey,签名
    46         $str .= 'key='.$privateKey;
    47         $sign = strtoupper(md5($str));
    48         return $sign;
    49     }
    50 
    51     // check value is or not empty
    52     //获取传入的参数,参数个数不确定,类型不确定
    53     public function handle($json)
    54     {
    55         // $params = func_get_args();  //结果是索引数组,不是关联数组
    56         $params = json_decode($json, true);
    57         $sign = $this->getSign($params, $this->privateKey);
    58         if($params['sign'] == $sign){
    59             return 'success';
    60         }else{
    61             return 'sign fail';
    62         }
    63     }
    64 }
    65 
    66 //模拟前端发送请求数据,使用json格式,func_get_args()返回的不是关联数组,无法使用签名。
    67 $user = 'bneglect';
    68 $timestamp = 1576659396;  //time()
    69 $str = '';
    70 $str .= 'timestamp='.$timestamp.'&user='.$user.'&key=thisisprivateKey!!';
    71 $sign = strtoupper(md5($str));
    72 $json = ['user'=>$user, 'timestamp'=>$timestamp, 'sign'=>$sign];
    73 $json = json_encode($json);
    74 
    75 //调用对象
    76 $token = new Token;
    77 echo $token->handle($json);
    View Code
原文地址:https://www.cnblogs.com/bneglect/p/12060930.html