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);