router_io.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { Socket, Server } from "socket.io";
  2. import { Auth } from '@d8d-appcontainer/auth';
  3. import type { User as AuthUser } from '@d8d-appcontainer/auth';
  4. import { APIClient } from '@d8d-appcontainer/api';
  5. import { setupMessageEvents } from './routes_io_messages.ts';
  6. import { setupExamEvents } from './routes_io_exam.ts';
  7. import debug from "debug";
  8. const log = debug('socketio:auth');
  9. interface SetupSocketIOProps {
  10. io: Server, auth: Auth, apiClient: APIClient
  11. }
  12. export interface SocketWithUser extends Socket {
  13. user?: AuthUser;
  14. }
  15. // 定义自定义上下文类型
  16. export interface Variables {
  17. socket: SocketWithUser
  18. auth: Auth
  19. user: AuthUser
  20. apiClient: APIClient
  21. // moduleDir: string
  22. // systemSettings?: SystemSettingRecord
  23. }
  24. export function setupSocketIO({ io, auth, apiClient }:SetupSocketIOProps) {
  25. // Socket.IO认证中间件
  26. io.use(async (socket: SocketWithUser) => {
  27. try {
  28. const token = socket.handshake.query.get('socket_token');
  29. if (!token) {
  30. log(`未提供token,拒绝连接: ${socket.id}`);
  31. throw new Error('未授权')
  32. }
  33. const userData = await auth.verifyToken(token);
  34. if (!userData) {
  35. log(`无效token,拒绝连接: ${socket.id}`);
  36. throw new Error('无效凭证')
  37. }
  38. socket.user = userData;
  39. log(`认证成功: ${socket.id} 用户: ${userData.username}`);
  40. } catch (error) {
  41. log(`认证错误: ${socket.id}`, error);
  42. }
  43. });
  44. io.on("connection", (socket: SocketWithUser) => {
  45. if (!socket.user) {
  46. socket.disconnect(true);
  47. return;
  48. }
  49. console.log(`socket ${socket.id} 已连接,用户: ${socket.user.username}`);
  50. socket.on("disconnect", (reason) => {
  51. console.log(`socket ${socket.id} 断开连接,原因: ${reason}`);
  52. });
  53. const context: Variables = {
  54. socket,
  55. auth,
  56. apiClient,
  57. user: socket.user,
  58. }
  59. // 初始化消息路由
  60. setupMessageEvents(context);
  61. setupExamEvents(context);
  62. });
  63. }