Secret.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <?php
  2. namespace components;
  3. use Yii;
  4. /**
  5. * Class Secret
  6. * @package components
  7. */
  8. class Secret
  9. {
  10. public $showErrorInfo = true;
  11. private $_contentType = 'application/json';
  12. private $_timeout = 300;
  13. private $_contentMd5 = '';
  14. private $_signatureMethod = 'md5';
  15. private $_signatureVersion = '1.0';
  16. private $_serverSignature = '';
  17. private $_clientSignature = '';
  18. /**
  19. * checkSignature
  20. * @param $client_id
  21. * @param $clientSignature
  22. */
  23. public function checkSignature($client_id, $clientSignature)
  24. {
  25. $this->_clientSignature = $clientSignature;
  26. $cone = $this->findOne($client_id);
  27. if (!$cone)
  28. static::throwError("client id avail.");
  29. $sKey = isset($client_id->client_key) ? $client_id->client_key : '';
  30. $headers = Yii::$app->request->getHeaders();
  31. if (!$headers)
  32. static::throwError("headers format avail.");
  33. $strVerb = $headers->get('verb');
  34. if (!$strVerb || !in_array((strtoupper($strVerb)), ['POST', 'GET']))
  35. static::throwError("headers verb avail.");
  36. $strMd5 = $headers->get('content-md5');
  37. if (!$this->checkContentMd5($strVerb, $strMd5, Yii::$app->request->getBodyParams()))
  38. static::throwError("headers content md5 avail.");
  39. $strContentType = $headers->get('content-type');
  40. if ($strContentType !== $this->_contentType)
  41. static::throwError("headers content type avail.");
  42. $strDate = strtotime($headers->get('date'));
  43. if ($strDate == false || $strDate-time() > 0 || time()-$strDate > $this->_timeout)
  44. static::throwError("headers date avail.");
  45. $strSM = $headers->get('signature-method');
  46. if (strtoupper($strSM) != strtoupper($this->_signatureMethod))
  47. static::throwError("headers signature method avail.");
  48. $strSV = $headers->get('signature-version');
  49. if ($strSV !== $this->_signatureVersion)
  50. static::throwError("headers signature version avail.");
  51. $str = "{$strVerb}\n\n{$strMd5}\n{$strContentType}\n{$strDate}\n{$strSM}\n{$strSV}\n\n{$sKey}\n";
  52. $base_sha1 = base64_encode(hash_hmac("sha1", $str, $sKey . '&', true));
  53. $this->_serverSignature = md5($base_sha1);
  54. if ($this->_serverSignature != '' && $this->_serverSignature !== $this->_clientSignature)
  55. static::throwError("Signature verification failed.");
  56. return true;
  57. }
  58. /**
  59. * findOne
  60. * @param $client_id
  61. */
  62. protected function findOne($client_id = false)
  63. {
  64. $model = new \common\models\Client();
  65. return $model::findOne(['client_id' => $client_id]);
  66. }
  67. /**
  68. * checkContentMd5
  69. * @param $verb
  70. * @param $md5
  71. * @param $post
  72. * @return bool
  73. */
  74. protected function checkContentMd5($verb, $md5, $post)
  75. {
  76. if ($verb == 'GET' && $md5 != '')
  77. return false;
  78. ksort($post);
  79. $this->_contentMd5 = md5(json_encode($post));
  80. if ( strtolower($md5) != strtolower($this->_contentMd5))
  81. return false;
  82. return true;
  83. }
  84. /**
  85. * throwError
  86. * @param $msg
  87. * @throws \yii\web\UnauthorizedHttpException
  88. */
  89. public function throwError($msg)
  90. {
  91. if ($this->showErrorInfo !== true)
  92. throw new \yii\web\UnauthorizedHttpException('Signature error');
  93. throw new \yii\web\UnauthorizedHttpException($msg);
  94. }
  95. }