Secret.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <?php
  2. namespace components;
  3. use Yii;
  4. use yii\base\Component;
  5. /**
  6. * Class Secret
  7. * @package components
  8. */
  9. class Secret extends Component
  10. {
  11. public $showErrorInfo = true;
  12. private $_contentType = 'application/json';
  13. private $_timeout = 300;
  14. private $_contentMd5 = '';
  15. private $_signatureMethod = 'md5';
  16. private $_signatureVersion = '1.0';
  17. private $_serverSignature = '';
  18. private $_clientSignature = '';
  19. /**
  20. * checkSignature
  21. * @param $client_id
  22. * @param $clientSignature
  23. */
  24. public function checkSignature($client_id, $clientSignature)
  25. {
  26. $this->_clientSignature = $clientSignature;
  27. $cone = $this->findOne($client_id);
  28. if (!$cone)
  29. static::throwError("client id avail.");
  30. $sKey = isset($cone->client_key) ? $cone->client_key : '';
  31. $headers = Yii::$app->request->getHeaders();
  32. if (!$headers)
  33. static::throwError("headers format avail.");
  34. $strVerb = strtoupper($headers->get('verb'));
  35. if (!$strVerb || !in_array(($strVerb), ['POST', 'GET']))
  36. static::throwError("headers verb avail.");
  37. $strMd5 = $headers->get('content-md5');
  38. if (!$this->checkContentMd5($strVerb, $strMd5, Yii::$app->request->getBodyParams())){
  39. // static::throwError("headers content md5 avail.");
  40. }
  41. $strContentType = $headers->get('content-type');
  42. if ($strContentType !== $this->_contentType){
  43. // static::throwError("headers content type avail.");
  44. }
  45. //$strDate = gmdate("D, d M Y H:i:s \G\M\T");
  46. $strDate = $headers->get('date');
  47. $strTime = strtotime($strDate);
  48. if ($strDate == false || $strTime-time() > 0 || time()-$strTime > $this->_timeout){
  49. // static::throwError("headers date avail.");
  50. }
  51. $strSM = $headers->get('signature-method');
  52. if (strtoupper($strSM) != strtoupper($this->_signatureMethod))
  53. static::throwError("headers signature method avail.");
  54. $strSV = $headers->get('signature-version');
  55. if ($strSV !== $this->_signatureVersion)
  56. static::throwError("headers signature version avail.");
  57. $str = "{$strVerb}\n\n{$strMd5}\n{$strContentType}\n{$strDate}\n{$strSM}\n{$strSV}\n\n{$sKey}\n";
  58. $base_sha1 = base64_encode(hash_hmac("sha1", $str, $sKey . '&', true));
  59. $this->_serverSignature = md5($base_sha1);
  60. if ($this->_serverSignature != '' && $this->_serverSignature !== $this->_clientSignature)
  61. // static::throwError("Signature verification failed.");
  62. return true;
  63. }
  64. /**
  65. * findOne
  66. * @param $client_id
  67. */
  68. protected function findOne($client_id = false)
  69. {
  70. $model = new \common\models\Client();
  71. return $model::findOne(['client_id' => $client_id]);
  72. }
  73. /**
  74. * checkContentMd5
  75. * @param $verb
  76. * @param $md5
  77. * @param $post
  78. * @return bool
  79. */
  80. protected function checkContentMd5($verb, $md5, $post)
  81. {
  82. if ($verb == 'GET' && $md5 != '')
  83. return false;
  84. if (!is_array($post))
  85. return true;
  86. $s = static::kSortParams($post);
  87. if (!$s)
  88. return true;
  89. $this->_contentMd5 = md5(json_encode($s));
  90. if ( strtolower($md5) != strtolower($this->_contentMd5))
  91. return false;
  92. return true;
  93. }
  94. /**
  95. * kSortParams
  96. * @param $arr
  97. * @return mixed
  98. */
  99. public static function kSortParams($arr)
  100. {
  101. foreach ($arr as $k => $v) {
  102. if ($v === [] || $v === '' || $v === null) {
  103. unset($arr[$k]);
  104. continue;
  105. }
  106. if (is_array($v))
  107. $arr[$k] = static::kSortParams($v);
  108. }
  109. ksort($arr);
  110. return $arr;
  111. }
  112. /**
  113. * throwError
  114. * @param $msg
  115. * @throws \yii\web\UnauthorizedHttpException
  116. */
  117. public function throwError($msg)
  118. {
  119. if ($this->showErrorInfo !== true)
  120. throw new \yii\web\UnauthorizedHttpException('Signature error');
  121. throw new \yii\web\UnauthorizedHttpException($msg);
  122. }
  123. }