Account.php 7.8 KB

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