Events.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace app\worker;
  15. /**
  16. * 推送主逻辑
  17. * 主要是处理 onMessage onClose
  18. */
  19. use GatewayWorker\Lib\Gateway;
  20. use app\worker\Application;
  21. use think\facade\Config;
  22. use Lcobucci\JWT\Builder;
  23. use Lcobucci\JWT\Parser;
  24. use thans\jwt\provider\JWT\Lcobucci;
  25. use utils\Aes;
  26. class Events
  27. {
  28. // 使用TP框架
  29. public static function onWorkerStart()
  30. {
  31. $app = new Application;
  32. $app->initialize();
  33. }
  34. // 当有客户端连接时,将client_id返回,让mvc框架判断当前uid并执行绑定
  35. public static function onConnect($client_id)
  36. {
  37. Gateway::sendToClient($client_id, json_encode(array(
  38. 'type' => 'init',
  39. 'client_id' => $client_id
  40. )));
  41. }
  42. /**
  43. * 有消息时
  44. * @param int $client_id
  45. * @param mixed $message
  46. */
  47. public static function onMessage($client_id, $message)
  48. {
  49. // 客户端传递的是json数据
  50. $message_data = json_decode($message, true);
  51. if(!$message_data)
  52. {
  53. return ;
  54. }
  55. // 根据类型执行不同的业务
  56. switch($message_data['type'])
  57. {
  58. // 客户端回应服务端的心跳
  59. case 'pong':
  60. break;
  61. case 'ping':
  62. self::sendStatus($client_id);
  63. break;
  64. case 'bindUid':
  65. self::auth($client_id,$message_data);
  66. break;
  67. }
  68. return;
  69. }
  70. protected static function sendStatus($client_id){
  71. $uid=$_SESSION['user_id'] ?? 0;
  72. $multiport=false;
  73. if($uid){
  74. $arr=Gateway::getClientIdByUid($uid);
  75. if(count($arr)>1){
  76. $multiport=true;
  77. }
  78. }
  79. Gateway::sendToClient($client_id, json_encode(array(
  80. 'type' => 'pong',
  81. 'multiport' => $multiport,
  82. )));
  83. }
  84. //验证用户的真实性并绑定
  85. protected static function auth($client_id, $msg){
  86. $token=$msg['token'] ?? '';
  87. $config = Config::get('jwt');
  88. $keys = $config['secret'] ?: [
  89. 'public' => $config['public_key'],
  90. 'private' => $config['private_key'],
  91. 'password' => $config['password'],
  92. ];
  93. $provider = new Lcobucci(new Builder(), new Parser(), $config['algo'], $keys);
  94. try {
  95. $token=str_replace('bearer ','',$token);
  96. $jwtData = $provider->decode((string)$token);
  97. } catch (\Exception $exception) {
  98. self::closeClient($client_id);
  99. }
  100. $userInfo = $jwtData['info']->getValue();
  101. //解密token中的用户信息
  102. $userInfo = Aes::decrypt($userInfo, config('app.aes_token_key'));
  103. //解析json
  104. $userInfo = (array)json_decode($userInfo, true);
  105. if(!$userInfo){
  106. self::closeClient($client_id);
  107. }
  108. $_SESSION['user_id']=$userInfo['user_id'];
  109. self::sendStatus($client_id);
  110. }
  111. //断开连接
  112. protected static function closeClient($client_id){
  113. $_SESSION['user_id']=null;
  114. Gateway::closeClient($client_id);
  115. }
  116. /**
  117. * 当断开连接时
  118. * @param int $client_id
  119. */
  120. public static function onClose($client_id)
  121. {
  122. $user_id=$_SESSION['user_id'];
  123. if($user_id){
  124. Gateway::sendToAll(json_encode(array(
  125. 'type' => 'isOnline',
  126. 'time' => time(),
  127. 'data' => ['id'=>$user_id,'is_online'=>0]
  128. )));
  129. }
  130. }
  131. }