Secret.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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($client_id->client_key) ? $client_id->client_key : '';
  31. $headers = Yii::$app->request->getHeaders();
  32. if (!$headers)
  33. static::throwError("headers format avail.");
  34. $strVerb = $headers->get('verb');
  35. if (!$strVerb || !in_array((strtoupper($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. $strContentType = $headers->get('content-type');
  41. if ($strContentType !== $this->_contentType)
  42. static::throwError("headers content type avail.");
  43. $strDate = strtotime($headers->get('date'));
  44. if ($strDate == false || $strDate-time() > 0 || time()-$strDate > $this->_timeout)
  45. static::throwError("headers date avail.");
  46. $strSM = $headers->get('signature-method');
  47. if (strtoupper($strSM) != strtoupper($this->_signatureMethod))
  48. static::throwError("headers signature method avail.");
  49. $strSV = $headers->get('signature-version');
  50. if ($strSV !== $this->_signatureVersion)
  51. static::throwError("headers signature version avail.");
  52. $str = "{$strVerb}\n\n{$strMd5}\n{$strContentType}\n{$strDate}\n{$strSM}\n{$strSV}\n\n{$sKey}\n";
  53. $base_sha1 = base64_encode(hash_hmac("sha1", $str, $sKey . '&', true));
  54. $this->_serverSignature = md5($base_sha1);
  55. if ($this->_serverSignature != '' && $this->_serverSignature !== $this->_clientSignature)
  56. static::throwError("Signature verification failed.");
  57. return true;
  58. }
  59. /**
  60. * findOne
  61. * @param $client_id
  62. */
  63. protected function findOne($client_id = false)
  64. {
  65. $model = new \common\models\Client();
  66. return $model::findOne(['client_id' => $client_id]);
  67. }
  68. /**
  69. * checkContentMd5
  70. * @param $verb
  71. * @param $md5
  72. * @param $post
  73. * @return bool
  74. */
  75. protected function checkContentMd5($verb, $md5, $post)
  76. {
  77. if ($verb == 'GET' && $md5 != '')
  78. return false;
  79. ksort($post);
  80. $k = array_keys($post);
  81. $s = $k ? implode('&', $k) : '';
  82. $this->_contentMd5 = md5($s);
  83. if ( strtolower($md5) != strtolower($this->_contentMd5))
  84. return false;
  85. return true;
  86. }
  87. /**
  88. * throwError
  89. * @param $msg
  90. * @throws \yii\web\UnauthorizedHttpException
  91. */
  92. public function throwError($msg)
  93. {
  94. if ($this->showErrorInfo !== true)
  95. throw new \yii\web\UnauthorizedHttpException('Signature error');
  96. throw new \yii\web\UnauthorizedHttpException($msg);
  97. }
  98. }