route.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <?php
  2. /**
  3. * This file is part of webman.
  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. use support\Request;
  15. use Webman\Route;
  16. use Webman\Push\Api;
  17. /**
  18. * 推送js客户端文件
  19. */
  20. Route::get('/plugin/webman/push/push.js', function (Request $request) {
  21. return response()->file(base_path().'/vendor/webman/push/src/push.js');
  22. });
  23. /**
  24. * 私有频道鉴权,这里应该使用session辨别当前用户身份,然后确定该用户是否有权限监听channel_name
  25. */
  26. Route::post(config('plugin.webman.push.app.auth'), function (Request $request) {
  27. $pusher = new Api(str_replace('0.0.0.0', '127.0.0.1', config('plugin.webman.push.app.api')), config('plugin.webman.push.app.app_key'), config('plugin.webman.push.app.app_secret'));
  28. $channel_name = $request->post('channel_name');
  29. $session = $request->session();
  30. // 这里应该通过session和channel_name判断当前用户是否有权限监听channel_name
  31. $has_authority = true;
  32. if ($has_authority) {
  33. return response($pusher->socketAuth($channel_name, $request->post('socket_id')));
  34. } else {
  35. return response('Forbidden', 403);
  36. }
  37. });
  38. /**
  39. * 当频道上线以及下线时触发的回调
  40. * 频道上线:是指某个频道从没有连接在线到有连接在线的事件
  41. * 频道下线:是指某个频道的所有连接都断开触发的事件
  42. */
  43. Route::post(parse_url(config('plugin.webman.push.app.channel_hook'), PHP_URL_PATH), function (Request $request) {
  44. // 没有x-pusher-signature头视为伪造请求
  45. if (!$webhook_signature = $request->header('x-pusher-signature')) {
  46. return response('401 Not authenticated', 401);
  47. }
  48. $body = $request->rawBody();
  49. // 计算签名,$app_secret 是双方使用的密钥,是保密的,外部无从得知
  50. $expected_signature = hash_hmac('sha256', $body, config('plugin.webman.push.app.app_secret'), false);
  51. // 安全校验,如果签名不一致可能是伪造的请求,返回401状态码
  52. if ($webhook_signature !== $expected_signature) {
  53. return response('401 Not authenticated', 401);
  54. }
  55. // 这里存储这上线 下线的channel数据
  56. $payload = json_decode($body, true);
  57. $channels_online = $channels_offline = [];
  58. foreach ($payload['events'] as $event) {
  59. if ($event['name'] === 'channel_added') {
  60. $channels_online[] = $event['channel'];
  61. } else if ($event['name'] === 'channel_removed') {
  62. $channels_offline[] = $event['channel'];
  63. }
  64. }
  65. // 业务根据需要处理上下线的channel,例如将在线状态写入数据库,通知其它channel等
  66. // 上线的所有channel
  67. echo 'online channels: ' . implode(',', $channels_online) . "\n";
  68. // 下线的所有channel
  69. echo 'offline channels: ' . implode(',', $channels_offline) . "\n";
  70. return 'OK';
  71. });