Account.php 8.5 KB

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