Secret.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. }
  31. $sKey = isset($cone->client_key) ? $cone->client_key : '';
  32. $headers = Yii::$app->request->getHeaders();
  33. if (!$headers){
  34. static::throwError("headers format avail.");
  35. }
  36. $strVerb = strtoupper($headers->get('verb'));
  37. if (!$strVerb || !in_array(($strVerb), ['POST', 'GET'])){
  38. static::throwError("headers verb avail.");
  39. }
  40. $strMd5 = $headers->get('content-md5');
  41. if (!$this->checkContentMd5($strVerb, $strMd5, Yii::$app->request->getBodyParams())){
  42. // static::throwError("headers content md5 avail.");
  43. }
  44. $strContentType = $headers->get('content-type');
  45. if ($strContentType !== $this->_contentType){
  46. // static::throwError("headers content type avail.");
  47. }
  48. //$strDate = gmdate("D, d M Y H:i:s \G\M\T");
  49. $strDate = $headers->get('date');
  50. $strTime = strtotime($strDate);
  51. if ($strDate == false || $strTime-time() > 0 || time()-$strTime > $this->_timeout){
  52. // static::throwError("headers date avail.");
  53. }
  54. $strSM = $headers->get('signature-method');
  55. if (strtoupper($strSM) != strtoupper($this->_signatureMethod)){
  56. static::throwError("headers signature method avail.");
  57. }
  58. $strSV = $headers->get('signature-version');
  59. if ($strSV !== $this->_signatureVersion){
  60. static::throwError("headers signature version avail.");
  61. }
  62. $str = "{$strVerb}\n\n{$strMd5}\n{$strContentType}\n{$strDate}\n{$strSM}\n{$strSV}\n\n{$sKey}\n";
  63. $base_sha1 = base64_encode(hash_hmac("sha1", $str, $sKey . '&', true));
  64. $this->_serverSignature = md5($base_sha1);
  65. if ($this->_serverSignature != '' && $this->_serverSignature !== $this->_clientSignature){
  66. // static::throwError("Signature verification failed.");
  67. }
  68. return true;
  69. }
  70. /**
  71. * findOne
  72. * @param $client_id
  73. */
  74. protected function findOne($client_id = false)
  75. {
  76. $model = new \common\models\Client();
  77. return $model::findOne(['client_id' => $client_id]);
  78. }
  79. /**
  80. * checkContentMd5
  81. * @param $verb
  82. * @param $md5
  83. * @param $post
  84. * @return bool
  85. */
  86. protected function checkContentMd5($verb, $md5, $post)
  87. {
  88. if ($verb == 'GET' && $md5 != '')
  89. return false;
  90. if (!is_array($post))
  91. return true;
  92. $s = static::kSortParams($post);
  93. if (!$s)
  94. return true;
  95. $this->_contentMd5 = md5(json_encode($s));
  96. if ( strtolower($md5) != strtolower($this->_contentMd5))
  97. return false;
  98. return true;
  99. }
  100. /**
  101. * kSortParams
  102. * @param $arr
  103. * @return mixed
  104. */
  105. public static function kSortParams($arr)
  106. {
  107. foreach ($arr as $k => $v) {
  108. if ($v === [] || $v === '' || $v === null) {
  109. unset($arr[$k]);
  110. continue;
  111. }
  112. if (is_array($v))
  113. $arr[$k] = static::kSortParams($v);
  114. }
  115. ksort($arr);
  116. return $arr;
  117. }
  118. /**
  119. * throwError
  120. * @param $msg
  121. * @throws \yii\web\UnauthorizedHttpException
  122. */
  123. public function throwError($msg)
  124. {
  125. if ($this->showErrorInfo !== true)
  126. throw new \yii\web\UnauthorizedHttpException('Signature error');
  127. throw new \yii\web\UnauthorizedHttpException($msg);
  128. }
  129. }