Tengo una ruta de inicio de sesión que eventualmente crea una cookie jwt llamada access_token . Después del inicio de sesión, el cliente recibirá esta cookie y la enviará en cada solicitud. Sin embargo, no encontré una forma de pasar esta cookie a Socket.io.
Ruta de inicio de sesión del lado del servidor:
const login = async (req, res) => { const {email, password} = req.body const user = await UserModel.findOne({email}) const isMatch = await user.checkPassword(password) if (isMatch) { const userToken = JwtService.createToken(user.id) return res.cookie("access_token", userToken, { httpOnly: true, secure: process.env.NODE_ENV === "production" }).status(200).json({user:user.toJSON(),message: 'login success'}) } }Zócalo:
this.io = new socketio.Server(expressServer, {cors: {origin: 'http://localhost:3000'}}) this.io.use((socket,next)=>{ console.log(socket.handshake.headers.cookie); // undefiend next() })Cliente :
this.socket = socketIOClient(process.env.SOCKET_BASE_URL, {auth: {userId}});servidor:
import express, {RequestHandler} from 'express'; import http from 'http' import cookieParser from "cookie-parser" import cors from 'cors'; import {router} from '@router'; import dotenv from 'dotenv' import mongoose from 'mongoose'; import {SocketService} from "@services"; const expressApp = express(); const port = process.env.PORT || 3001; dotenv.config() expressApp.use(cors({ origin: true, credentials: true })); expressApp.use(express.json() as RequestHandler); expressApp.use(cookieParser()); expressApp.use('/', router) const httpServer = http.createServer(expressApp); new SocketService(httpServer) httpServer.listen(port, async () => { console.log(`server is listening on ${port}`); try { await mongoose.connect('mongodb://guess-it-mongo-dev:27017/guess-it', {connectTimeoutMS: 1000}); console.log('connected to mongo server') } catch (e) { console.log(e); } }); Suponiendo que solo tiene una cookie, que es su jwt , puede obtenerla con el parámetro de socket de la siguiente manera:
const token = socket.handshake.headers.cookie.split("=")[1]; Si tiene muchas cookies, necesita usar algún analizador de cookies y darle socket.handshake.headers.cookie para analizarlo, por ejemplo:
function getCookie(cName) { const name = cName + "="; const cDecoded = decodeURIComponent(socket.handshake.headers.cookie); const cArr = cDecoded.split(';'); let res; cArr.forEach(val => { if (val.indexOf(name) === 0) res = val.substring(name.length); }) return res; } const token = getCookie("jwt"); // if your token is called jwt.Si la solución dada no funciona para usted, asegúrese de configurar su aplicación y socket de esta manera para tenerlos como un solo servidor (siéntase libre de cambiar el puerto):
const app = express(); const http = require("http"); const server = http.createServer(app); const { Server } = require("socket.io"); const io = new Server(server); server.listen(9000, () => { console.log("server runnig on port " + 9000); });Y el cliente debería conectarse así (con el mismo puerto que el servidor):
import { io } from "socket.io-client"; io("http://localhost:9000/", { transports: ["websocket"], });Por ejemplo, en el siguiente código, autentico cada conexión con un middleware :
io.use((socket, next) => { const token = socket.handshake.headers.cookie.split("=")[1]; if (token) { jwt.verify(token, process.env.SECRET, (err, decodedToken) => { if (err) { next(new Error("invalid")); } else { User.findById(decodedToken.id, function (err, user) { if (err) { next(new Error("invalid")); } else { next(); } }); } }); } else { next(new Error("invalid")); } }); //if authentication is ok, the code below will get executed io.on("connection", (socket) => { // do things })