[NODEJS] EXPRESS(node.js) to WebSocket 세션 공유

EXPRESS(node.js) to WebSocket 세션 공유

Express로 웹서버 생성 후 서버 및 세션정보를 WebSocket으로 전달
WebSocket 서버 생성 시 verifyClient 옵션으로 세션 처리

server.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import bodyParser from "body-parser";
import cors from "cors";
import express from "express";
import http from "http";
import methodOverride from "method-override";
import morgan from "morgan";
import session from "express-session";
import passport from "passport";
import path from "path";

import { WS } from "./app/ws";
.
.
.
export class Server {
/* private static ConnectDB(): Promise<any> {
return Connection;
} */
private readonly app: express.Application;
private readonly server: http.Server;

constructor() {
this.app = express();
this.server = http.createServer(this.app);
}

.
.
.

private ExpressConfiguration(): void {
// const RedisStore = connectRedis(session);
const cookieOptions = {
maxAge: 1000 * 60 * 60,
// secure:true, 브라우저가 HTTPS를 통해서만 쿠키를 전송하도록 합니다.
httpOnly: false,
// 쿠키가 클라이언트 JavaScript가 아닌 HTTP(S)를 통해서만 전송되도록 하며, 이를 통해 XSS(Cross-site scripting) 공격으로부터 보호할 수 있습니다.
};
const sessionInfo = {
secret: "sec",
resave: true,
saveUninitialized: true,
cookie: cookieOptions,
// store: new RedisStore(config.REDIS_OPTS),
};
this.sessionOptions = session(sessionInfo);
this.app.use(bodyParser.urlencoded({extended: true}));
this.app.use(bodyParser.json({limit: "50mb"}));
this.app.use(this.sessionOptions);
/* this.app.use(session(
{
resave: true,
saveUninitialized: true,
secret: config.SECRET,
store: new RedisStore(config.REDIS_OPTS),
},
)); */
this.app.use(passport.initialize());
this.app.use(passport.session());
this.app.use(methodOverride());
// const viewpath = path.join(__dirname, "../views");
// serverService.debug(viewpath);
// this.app.set("views", "./views");
this.app.set('views', path.join(__dirname, 'views'));
this.app.set("view engine", "ejs");

this.app.use((req, res, next): void => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization");
res.header("Access-Control-Allow-Methods", "GET,PUT,PATCH,POST,DELETE,OPTIONS");
next();
});
this.app.use(morgan("combined"));
this.app.use(cors());

this.app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction): void => {
err.status = 404;
next(err);
});
}

private setWebSocket(): void {
this.ws = new WS(this.server, this.sessionOptions);
}
}

ws.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import WebSocket from 'ws';
import express, { Router } from "express";
import http from "http";

.
.
.

export class WS {
private wss: WebSocket.Server;
private server: http.Server;
private session: express.RequestHandler;

constructor(server: http.Server, session: express.RequestHandler) {
this.server = server;
this.session = session;
this.init(server, session);
}

private init(serve: http.Server, session: any) {
this.wss = new WebSocket.Server({

verifyClient:(info: {origin: string; secure: boolean; req: any }, done) => {
console.log('Parsing session from request...');
session(info.req,( )=>{}, ()=>{
if(this.isSessionPassport(info.req)){
done(info.req.session);
}else{
// done(false,401,'unathorized');
done(true);
}
console.log(info.req.session.id);

})
}, server: serve
, path: "/"
});
/* this.pushController = new PushController(this.wss);
this.pushController.startPush(); */
this.connection();
}

private connection(){
this.wss.on("connection",(ws: WebSocket) => {
// this.pushController.broadcastPush("100" , "msg");
ws.on("message", (msg: string) => {
console.log(msg);
})
});
}

private isSessionPassport(req: express.Request){
if(req.session.passport && req.session.passport.user){
console.log(req.session.passport.user);
return true;
}else{
console.log("no passport");
return false;
}
}

}