123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- <?php
- namespace components;
- use Yii;
- use yii\base\Component;
- /**
- * Class Secret
- * @package components
- */
- class Secret extends Component
- {
- public $showErrorInfo = true;
- private $_contentType = 'application/json';
- private $_timeout = 300;
- private $_contentMd5 = '';
- private $_signatureMethod = 'md5';
- private $_signatureVersion = '1.0';
- private $_serverSignature = '';
- private $_clientSignature = '';
- /**
- * checkSignature
- * @param $client_id
- * @param $clientSignature
- */
- public function checkSignature($client_id, $clientSignature)
- {
- $this->_clientSignature = $clientSignature;
- $cone = $this->findOne($client_id);
- if (!$cone){
- static::throwError("client id avail.");
- }
- $sKey = isset($cone->client_key) ? $cone->client_key : '';
- $headers = Yii::$app->request->getHeaders();
- if (!$headers){
- static::throwError("headers format avail.");
- }
- $strVerb = strtoupper($headers->get('verb'));
- if (!$strVerb || !in_array(($strVerb), ['POST', 'GET'])){
- static::throwError("headers verb avail.");
- }
- $strMd5 = $headers->get('content-md5');
- if (!$this->checkContentMd5($strVerb, $strMd5, Yii::$app->request->getBodyParams())){
- // static::throwError("headers content md5 avail.");
- }
- $strContentType = $headers->get('content-type');
- if ($strContentType !== $this->_contentType){
- // static::throwError("headers content type avail.");
- }
- //$strDate = gmdate("D, d M Y H:i:s \G\M\T");
- $strDate = $headers->get('date');
- $strTime = strtotime($strDate);
- if ($strDate == false || $strTime-time() > 0 || time()-$strTime > $this->_timeout){
- // static::throwError("headers date avail.");
- }
- $strSM = $headers->get('signature-method');
- if (strtoupper($strSM) != strtoupper($this->_signatureMethod)){
- static::throwError("headers signature method avail.");
- }
- $strSV = $headers->get('signature-version');
- if ($strSV !== $this->_signatureVersion){
- static::throwError("headers signature version avail.");
- }
- $str = "{$strVerb}\n\n{$strMd5}\n{$strContentType}\n{$strDate}\n{$strSM}\n{$strSV}\n\n{$sKey}\n";
- $base_sha1 = base64_encode(hash_hmac("sha1", $str, $sKey . '&', true));
- $this->_serverSignature = md5($base_sha1);
- if ($this->_serverSignature != '' && $this->_serverSignature !== $this->_clientSignature){
- // static::throwError("Signature verification failed.");
- }
- return true;
- }
- /**
- * findOne
- * @param $client_id
- */
- protected function findOne($client_id = false)
- {
- $model = new \common\models\Client();
- return $model::findOne(['client_id' => $client_id]);
- }
- /**
- * checkContentMd5
- * @param $verb
- * @param $md5
- * @param $post
- * @return bool
- */
- protected function checkContentMd5($verb, $md5, $post)
- {
- if ($verb == 'GET' && $md5 != '')
- return false;
- if (!is_array($post))
- return true;
- $s = static::kSortParams($post);
- if (!$s)
- return true;
- $this->_contentMd5 = md5(json_encode($s));
- if ( strtolower($md5) != strtolower($this->_contentMd5))
- return false;
- return true;
- }
- /**
- * kSortParams
- * @param $arr
- * @return mixed
- */
- public static function kSortParams($arr)
- {
- foreach ($arr as $k => $v) {
- if ($v === [] || $v === '' || $v === null) {
- unset($arr[$k]);
- continue;
- }
- if (is_array($v))
- $arr[$k] = static::kSortParams($v);
- }
- ksort($arr);
- return $arr;
- }
- /**
- * throwError
- * @param $msg
- * @throws \yii\web\UnauthorizedHttpException
- */
- public function throwError($msg)
- {
- if ($this->showErrorInfo !== true)
- throw new \yii\web\UnauthorizedHttpException('Signature error');
- throw new \yii\web\UnauthorizedHttpException($msg);
- }
- }
|