CheckSignUtil.php 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. <?php
  2. namespace app\utils;
  3. use think\Request;
  4. /**
  5. * 校验sign 校验签名,防止刷重要接口
  6. */
  7. class CheckSignUtil{
  8. /**
  9. * 校验接口名单
  10. */
  11. const hitList = [
  12. 'api/gift/givegift_typing',// 聊天赠送礼物
  13. 'api/usercenter/chat_once',// 文字聊天扣费
  14. 'api/usercenter/voice_onemin',// 语音聊天扣费
  15. 'api/usercenter/videochat_onemin',// 视频聊天扣费
  16. ];
  17. /**
  18. * 失效时间 单位 seconds
  19. */
  20. const deadTime = 150;
  21. /**
  22. * 校验签名
  23. * @param $path
  24. * @param $token
  25. * @param $sign
  26. * @return array
  27. */
  28. public static function check($path,$token,$sign): array
  29. {
  30. if (!in_array($path,self::hitList)){
  31. return [true,'success'];
  32. }
  33. if (empty($sign)){
  34. return [false,'签名缺失!'];
  35. }
  36. // 签名解密
  37. $rsa = new RsaUtil();
  38. $sign = $rsa->privateDecrypt($sign);
  39. if (!$sign || !$sign = json_decode($sign,true)){
  40. return [false,'签名错误!'];
  41. }
  42. if (empty($sign['token']) || empty($sign['timestamp']) || empty($sign['timezone'])){
  43. return [false,'签名参数错误!'];
  44. }
  45. if ($token != $sign['token']){
  46. return [false,'签名参数校验错误!'];
  47. }
  48. if ($token != $sign['token']){
  49. return [false,'签名参数校验错误!'];
  50. }
  51. // 根据客户端 时区 校验时间戳
  52. $now = new \DateTime(null, new \DateTimeZone((string)$sign['timezone']));
  53. $time = (int)($now->format('U'));
  54. // 如果 前端请求时间戳异常,则认为 请求被篡改 或 请求超时
  55. if ($sign['timestamp'] <= ($time - self::deadTime)){
  56. return [false,'签名过期,请求已过期!'];
  57. }
  58. // 请求唯一key
  59. $key = md5($sign['token'] . '_' .((string)$sign['timestamp']));
  60. // redis 重复请求
  61. if (!RedisUtil::getInstance('check_sign_lock',$key)->tryTimes(self::deadTime,1)) {
  62. return [false,'点的太快啦!'];
  63. }
  64. return [true,'success'];
  65. }
  66. }