Auth.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. declare(strict_types = 1);
  3. namespace hg\apidoc;
  4. use hg\apidoc\exception\ErrorException;
  5. use hg\apidoc\utils\ConfigProvider;
  6. use hg\apidoc\utils\Helper;
  7. class Auth
  8. {
  9. protected $authConfig = [];
  10. public function __construct($config)
  11. {
  12. $authConfig = !empty($config['auth'])?$config['auth']:[];
  13. if (empty($authConfig['secret_key'])){
  14. $authConfig['secret_key'] = "apidoc#hgcode";
  15. }
  16. if (empty($authConfig['expire'])){
  17. $authConfig['expire'] = 86400;
  18. }
  19. $this->authConfig = $authConfig;
  20. }
  21. /**
  22. * 验证密码是否正确
  23. * @param $password
  24. * @return false|string
  25. */
  26. public function verifyAuth(string $password, string $appKey)
  27. {
  28. $authConfig = $this->authConfig;
  29. if (!empty($appKey)) {
  30. $currentAppConfig = Helper::getCurrentAppConfig($appKey);
  31. $currentApp = $currentAppConfig['appConfig'];
  32. if (!empty($currentApp) && !empty($currentApp['password'])) {
  33. // 应用密码
  34. if (md5($currentApp['password']) === $password) {
  35. return $this->createToken($currentApp['password'],$authConfig['expire']);
  36. }
  37. throw new ErrorException("password error");
  38. }
  39. }
  40. if ($authConfig['enable']) {
  41. // 密码验证
  42. if (md5($authConfig['password']) === $password) {
  43. return $this->createToken($authConfig['password'],$authConfig['expire']);
  44. }
  45. throw new ErrorException("password error");
  46. }
  47. return false;
  48. }
  49. /**
  50. * 验证token是否可用
  51. * @param $request
  52. * @return bool
  53. */
  54. public function checkAuth($params=[]): bool
  55. {
  56. $authConfig = $this->authConfig;
  57. $token = !empty($params['token'])?$params['token']:"";
  58. $appKey = !empty($params['appKey'])?$params['appKey']:"";
  59. if (!empty($appKey)) {
  60. $currentAppConfig = Helper::getCurrentAppConfig($appKey);
  61. $currentApp = $currentAppConfig['appConfig'];
  62. if (!empty($currentApp) && !empty($currentApp['password'])) {
  63. if (empty($token)) {
  64. throw new ErrorException("token not found");
  65. }
  66. // 应用密码
  67. if ($this->checkToken($token, $currentApp['password'])) {
  68. return true;
  69. } else {
  70. throw new ErrorException("token error");
  71. }
  72. } else if (empty($authConfig['enable'])) {
  73. return true;
  74. }
  75. }
  76. if($authConfig['enable'] && empty($token)){
  77. throw new ErrorException("token not found");
  78. }else if (!empty($token) && !$this->checkToken($token, "") && $authConfig['enable']) {
  79. throw new ErrorException("token error");
  80. }
  81. return true;
  82. }
  83. /**
  84. * 获取tokencode
  85. * @param string $password
  86. * @return string
  87. */
  88. protected static function getTokenCode(string $password): string
  89. {
  90. return md5(md5($password));
  91. }
  92. /**
  93. * 创建token
  94. * @param string $password
  95. * @return string
  96. */
  97. public function createToken(string $password): string
  98. {
  99. $authConfig = $this->authConfig;
  100. $data = [
  101. 'key'=>static::getTokenCode($password),
  102. 'expire'=>time()+$authConfig['expire']
  103. ];
  104. $code = json_encode($data);
  105. return static::handleToken($code, "CE",$authConfig['secret_key']);
  106. }
  107. /**
  108. * 验证token是否可用
  109. * @param $token
  110. * @return bool
  111. */
  112. public function checkToken(string $token, string $password): bool
  113. {
  114. $authConfig = $this->authConfig;
  115. if (empty($password)){
  116. $password = $authConfig['password'];
  117. }
  118. $decode = static::handleToken($token, "DE",$authConfig['secret_key']);
  119. $deData = json_decode($decode,true);
  120. if (!empty($deData['key']) && $deData['key'] === static::getTokenCode($password) && !empty($deData['expire']) && $deData['expire']>time()){
  121. return true;
  122. }
  123. return false;
  124. }
  125. /**
  126. * 处理token
  127. * @param $string
  128. * @param string $operation
  129. * @param string $key
  130. * @param int $expiry
  131. * @return false|string
  132. */
  133. protected static function handleToken(string $string, string $operation = 'DE', string $key = '', int $expiry = 0):string
  134. {
  135. $ckey_length = 4;
  136. $key = md5($key);
  137. $keya = md5(substr($key, 0, 16));
  138. $keyb = md5(substr($key, 16, 16));
  139. $keyc = $ckey_length ? ($operation == 'DE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
  140. $cryptkey = $keya . md5($keya . $keyc);
  141. $key_length = strlen($cryptkey);
  142. $string = $operation == 'DE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
  143. $string_length = strlen($string);
  144. $result = '';
  145. $box = range(0, 255);
  146. $rndkey = array();
  147. for ($i = 0; $i <= 255; $i++) {
  148. $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  149. }
  150. for ($j = $i = 0; $i < 256; $i++) {
  151. $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  152. $tmp = $box[$i];
  153. $box[$i] = $box[$j];
  154. $box[$j] = $tmp;
  155. }
  156. for ($a = $j = $i = 0; $i < $string_length; $i++) {
  157. $a = ($a + 1) % 256;
  158. $j = ($j + $box[$a]) % 256;
  159. $tmp = $box[$a];
  160. $box[$a] = $box[$j];
  161. $box[$j] = $tmp;
  162. $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  163. }
  164. if ($operation == 'DE') {
  165. $subNumber = (int)substr($result, 0, 10);
  166. if (($subNumber == 0 || $subNumber - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
  167. return substr($result, 26);
  168. } else {
  169. return '';
  170. }
  171. } else {
  172. return $keyc . str_replace('=', '', base64_encode($result));
  173. }
  174. }
  175. }