Account.php 8.9 KB

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