route.php 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. print_r($request->post());
  28. $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'));
  29. $channel_name = $request->post('channel_name');
  30. $session = $request->session();
  31. // 这里应该通过session和channel_name判断当前用户是否有权限监听channel_name
  32. $has_authority = true;
  33. if ($has_authority) {
  34. return response($pusher->socketAuth($channel_name, $request->post('socket_id')));
  35. } else {
  36. return response('Forbidden', 403);
  37. }
  38. });
  39. /**
  40. * 当频道上线以及下线时触发的回调
  41. * 频道上线:是指某个频道从没有连接在线到有连接在线的事件
  42. * 频道下线:是指某个频道的所有连接都断开触发的事件
  43. */
  44. Route::post(parse_url(config('plugin.webman.push.app.channel_hook'), PHP_URL_PATH), function (Request $request) {
  45. // 没有x-pusher-signature头视为伪造请求
  46. if (!$webhook_signature = $request->header('x-pusher-signature')) {
  47. return response('401 Not authenticated', 401);
  48. }
  49. $body = $request->rawBody();
  50. // 计算签名,$app_secret 是双方使用的密钥,是保密的,外部无从得知
  51. $expected_signature = hash_hmac('sha256', $body, config('plugin.webman.push.app.app_secret'), false);
  52. // 安全校验,如果签名不一致可能是伪造的请求,返回401状态码
  53. if ($webhook_signature !== $expected_signature) {
  54. return response('401 Not authenticated', 401);
  55. }
  56. // 这里存储这上线 下线的channel数据
  57. $payload = json_decode($body, true);
  58. $channels_online = $channels_offline = [];
  59. foreach ($payload['events'] as $event) {
  60. if ($event['name'] === 'channel_added') {
  61. $channels_online[] = $event['channel'];
  62. } else if ($event['name'] === 'channel_removed') {
  63. $channels_offline[] = $event['channel'];
  64. }
  65. }
  66. // 业务根据需要处理上下线的channel,例如将在线状态写入数据库,通知其它channel等
  67. // 上线的所有channel
  68. echo 'online channels: ' . implode(',', $channels_online) . "\n";
  69. // 下线的所有channel
  70. echo 'offline channels: ' . implode(',', $channels_offline) . "\n";
  71. return 'OK';
  72. });