首页 > 解决方案 > socket.io:cookie 未在初始连接时发送

问题描述

我意识到这已经被问过很多次了,但是我已经阅读了所有这些,但我还没有找到解决方案。我使用会话授权(express-session)和我检查过的所有其他请求,它们在标题(req.headers)中都有正确的cookie。

图片

但是在检查套接字 io 连接的标头时,标头中没有 cookie,因此我无法进行授权。我真的不想使用 JWT,因为我相信我必须将数据存储在本地存储中,这有点不安全(我不是专家),我也可以使用刷新令牌,但我只想为他们的会话使用简单。这是代码:

import express from "express";
import bodyParser from "body-parser";
import cors from "cors";
import {handleError, ErrorHandler} from "./helpers/error"
import mongoose from "mongoose";
import config from "./config"
import http from "http";
import {Server, Socket} from "socket.io";
import routes from "./routes";
import session from "express-session";
import Message from "./models/Message";

// express session not allowing to alter req.session object, just why?
declare module 'express-session' {
    interface SessionData {
      userId: mongoose.Types.ObjectId;
    }
}

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
    cors: {
        origin: config.CLIENT_URL,
        credentials: true
    }
});

//middleware
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({extended: true}))
app.use(cors({ origin: config.CLIENT_URL, credentials: true}));

const sessionMiddleware = session({
    secret: config.SESSION_SECRET!,
    saveUninitialized: true,                          <== not implemented Redis yet
    resave: true
})

app.use(sessionMiddleware);
io.use((socket, next) => {
    sessionMiddleware(
        socket.request as express.Request, 
        {} as express.Response, 
        next as express.NextFunction 
    );
})

//loaders
import "./loaders/mongoose" //start mongoose connection

mongoose.connection.on("connected", () => {
    console.log("connected to mongodb");
})

mongoose.connection.on("error", () => {
    console.log("error when connecting to mongodb")
})

// socket.io

io.on("connection", (socket: any) => {
    console.log("User connected")
    console.log(socket.handshake.headers)
    // console.log(socket.handshake.query)
})


//routes
app.use("/api", routes);

app.get("/api/test", async (req,res, next) => {
    console.log(req.headers)
    res.send();
})

server.listen(config.PORT, () => {
    console.log(`listening on port ${config.PORT}`)
})

//catch 404
app.use((req,res,next) => {
    const err = new ErrorHandler(404, "Not found!");
    next(err);
})

//error handlers
app.use((
    err: ErrorHandler, 
    req: any, 
    res: express.Response, 
    next: any
) => {
    handleError(err, res);
})

这是 socket.handshake.headers 的标头的样子:

图片

和一些客户端代码:

import React, { useEffect } from 'react';
import DrawCanvas from "./DrawCanvas";
import io from "socket.io-client";
import axios from "axiosBase";

function App() {

  useEffect(() => {
    let newSocket:SocketIOClient.Socket;
    (async () => {
      //example test
      await axios.post("/users/login", {
        username: "jake",
        password: "123",
        email: "example@me.com"
      })
      await axios.get("/test", {withCredentials: true}) //this recieves the cookies fine!
      console.log("logged in")

      newSocket = io(
        "http://localhost:5000", 
        { query: {id: 123}, transportOptions: {
          withCredentials: true //doesn't show this in documentation of v4 but I found it somehow??
        }}
      )

  
    })()
   
    return () => {newSocket.close()}
  
  }, [])

  return (
    <DrawCanvas />
  );
}

标签: node.jstypescriptsocket.io

解决方案


推荐阅读