Account.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <?php
  2. /**
  3. * 用户基础信息
  4. * @author benzhan
  5. */
  6. use kornrunner\Keccak;
  7. class Account extends Model {
  8. protected $tableName = 'user_info';
  9. protected $dbKey = 'dw_chat';
  10. const PRE_KEY_TOKEN = 'globals:token:';
  11. const PRE_KEY_RANDOM = 'globals:random_1:';
  12. const PRE_KEY_ACCESS_TOKEN = 'globals:access_token:';
  13. const TYPE_EOS = 'eos';
  14. const TYPE_ETH = 'eth';
  15. const TYPE_TRON = 'tron';
  16. private static $arrType = [
  17. self::TYPE_EOS => 'EOS',
  18. self::TYPE_ETH => 'ETH',
  19. self::TYPE_TRON => 'TRON',
  20. ];
  21. public static function getAllType() {
  22. return self::$arrType;
  23. }
  24. public static function getTokenKey($token) {
  25. return self::PRE_KEY_TOKEN . $token;
  26. }
  27. /**
  28. * 检查token是否存在
  29. * @param $player
  30. *
  31. * @return bool
  32. */
  33. public static function checkToken() {
  34. $objRedis = dwRedis::init('dw_chat');
  35. if ($_REQUEST['token'] && $_REQUEST['user_id']) {
  36. $token = $_REQUEST['token'];
  37. $user_id = $_REQUEST['user_id'];
  38. } else {
  39. $token = $_COOKIE['token'];
  40. $user_id = $_COOKIE['user_id'];
  41. }
  42. if ($token) {
  43. $tokenKey = self::getTokenKey($token);
  44. $value = $objRedis->get($tokenKey);
  45. if ($value) {
  46. if ($value == $user_id) {
  47. return true;
  48. }
  49. } else {
  50. self::clearCookie();
  51. }
  52. }
  53. return false;
  54. }
  55. /**
  56. * 生成账号
  57. */
  58. public static function genToken($user_id) {
  59. $token = uuid16();
  60. $tokenKey = self::getTokenKey($token);
  61. $objRedis = dwRedis::init();
  62. // $objRedis->set($tokenKey, $account);
  63. $objRedis->setex($tokenKey, 86400, $user_id);
  64. return $token;
  65. }
  66. /**
  67. * 设置用户的Cookie
  68. * @param $account
  69. *
  70. * @return array
  71. */
  72. public static function setCookie($user_id) {
  73. $token = Account::genToken($user_id);
  74. $expire = time() + 86400 * 7;
  75. $path = '/';
  76. $domain = '';
  77. if (ENV != ENV_DEV) {
  78. $domain = 'mee.chat';
  79. }
  80. // 生成token
  81. setcookie('token', $token, $expire, $path, $domain);
  82. setcookie('user_id', $user_id, $expire, $path, $domain);
  83. return compact('user_id', 'token');
  84. }
  85. public static function clearCookie() {
  86. $expire = time() - 86400;
  87. $path = '/';
  88. // 删除正式环境的cookie
  89. setcookie('token', null, $expire, $path, 'mee.chat');
  90. setcookie('user_id', null, $expire, $path, 'mee.chat');
  91. if (ENV == ENV_DEV) {
  92. // 删除cookie
  93. setcookie('token', null, $expire, $path);
  94. setcookie('user_id', null, $expire, $path);
  95. }
  96. }
  97. public static function getRandomKey($account) {
  98. return self::PRE_KEY_RANDOM . $account;
  99. }
  100. private static function getAccessTokenKey($accessToken) {
  101. return self::PRE_KEY_ACCESS_TOKEN . $accessToken;
  102. }
  103. /**
  104. * 刷新access_token
  105. * @author solu
  106. * @param $random
  107. * @param null $objRedis
  108. * @return string
  109. */
  110. private static function refreshAccessToken($random, $objRedis = null) {
  111. !$objRedis && $objRedis = dwRedis::init();
  112. $accessToken = uuid();
  113. $key = self::getAccessTokenKey($accessToken);
  114. $objRedis->setex($key, 900, $random);
  115. return $accessToken;
  116. }
  117. /**
  118. * 获取随机数
  119. * @param $account
  120. * @param $withToken
  121. * @return string|array
  122. */
  123. public static function getRandom($account, $withToken = false) {
  124. $objRedis = dwRedis::init();
  125. $randomKey = self::getRandomKey($account);
  126. $random = $objRedis->get($randomKey);
  127. if (!$random) {
  128. // $random = uuid16();
  129. $random = date('H:i:s ', time() - 8 * 3600) . rand(0, 999);
  130. }
  131. $objRedis->setex($randomKey, 900, $random);
  132. $accessToken = self::refreshAccessToken($random, $objRedis);
  133. return !$withToken ? $random : compact('random', 'accessToken');
  134. }
  135. /**
  136. * 校验用户并且登录
  137. * @author solu
  138. * @param $account
  139. * @param $random
  140. * @param $token
  141. * @return array
  142. * @throws Exception
  143. */
  144. public static function verifyPlayer($account, $random, $token) {
  145. if (!$account) {
  146. throw new Exception('参数错误', CODE_PARAM_ERROR);
  147. }
  148. $objRedis = dwRedis::init();
  149. $tokenKey = self::getAccessTokenKey($token);
  150. $storeRandom = $objRedis->get($tokenKey);
  151. if ($storeRandom != $random) {
  152. throw new Exception('access_token unmatch', CODE_PARAM_ERROR);
  153. }
  154. $user_id = User::login($account, Account::TYPE_EOS);
  155. return self::setCookie($user_id);
  156. }
  157. /**
  158. * 校验eos
  159. * @param $pubkey
  160. * @param $account
  161. * @param $data
  162. * @param $sign
  163. * @return bool
  164. * @throws Exception
  165. */
  166. public static function verifyMsg($pubkey, $account, $data, $sign) {
  167. $json = EosBase::getAccount($account);
  168. $user = json_decode($json, true);
  169. // $user = EosRpcApi::getAccount($account);
  170. $active = $user['permissions'][0]['required_auth']['keys'][0]['key'];
  171. $owner = $user['permissions'][1]['required_auth']['keys'][0]['key'];
  172. if ($pubkey != $active && $pubkey != $owner) {
  173. throw new Exception('pubkey error', CODE_PARAM_ERROR);
  174. }
  175. $cmd = "node {$GLOBALS['verifyPath']} '$data' '$pubkey' '$sign'";
  176. // 返回true表示验证通过
  177. $ret = EosBase::execCmd($cmd);
  178. return trim($ret) == 'true';
  179. }
  180. /**
  181. * 校验eth签名
  182. * @author solu
  183. * @param $account
  184. * @param $data
  185. * @param $signed
  186. * @return bool
  187. * @throws Exception
  188. */
  189. public static function verifyEth($account, $data, $signed) {
  190. $hash = Utils::sha3($data);
  191. $messageGmp = gmp_init($hash);
  192. $rHex = substr($signed, 2, 64);
  193. $sHex = substr($signed, 66, 64);
  194. $vValue = hexdec(substr($signed, 130, 2));
  195. $r = $rHex; //hex string without 0x
  196. $s = $sHex; //hex string without 0x
  197. $v = $vValue; //27 or 28
  198. $rGmp = gmp_init("0x" . $r);
  199. $sGmp = gmp_init("0x" . $s);
  200. $recovery = $v - 27;
  201. if ($recovery !== 0 && $recovery !== 1) {
  202. throw new Exception('Invalid signature v value');
  203. }
  204. $publicKey = Signature::recoverPublicKey($rGmp, $sGmp, $messageGmp, $recovery);
  205. $publicKeyString = $publicKey["x"] . $publicKey["y"];
  206. $recoveryAccount = '0x'. substr(self::keccak256(hex2bin($publicKeyString)), -40);
  207. return strtolower($recoveryAccount) == strtolower($account);
  208. }
  209. /**
  210. * 校验tron签名
  211. * @author solu
  212. * @param $account
  213. * @param $data
  214. * @param $signed
  215. * @return bool
  216. */
  217. public static function verifyTron($account, $data, $signed) {
  218. $data = Utils::sha3($data);
  219. $cmd = "node {$GLOBALS['tronVerifyPath']} '$data' '$signed' '$account'";
  220. // 返回true表示验证通过
  221. $ret = EosBase::execCmd($cmd);
  222. return trim($ret) == 'true';
  223. }
  224. /**
  225. * keccak256
  226. * @param $str
  227. * @return string
  228. * @throws Exception
  229. */
  230. private static function keccak256($str) {
  231. return '0x'. Keccak::hash($str, 256);
  232. }
  233. }