NodeJS:在服务器呈现的视图和 React 应用程序之间共享会话的最佳方式是什么
NodeJS: What's the best way to share session between server-rendered views and React app
我有一个从服务器呈现页面的 NodeJS (Koa) 服务器应用程序,即 nunjucks/jade/etc。登录页面也是服务器呈现的。登录后,将创建 cookie。
现在我正在构建一个将嵌入到安全页面中的 React 应用程序(在用户登录后)。让 React 应用程序使用用户当前登录的会话向服务器发出安全 Http/Websocket 请求的最佳方式是什么?
目前,我正在将 sessionId 注入到加载 React 应用程序的服务器呈现页面的脚本标记中。所以...
服务器:
var session = require('koa-generic-session');
app.use(session({
store: redisStore(...)
}));
app.use(function*(next) {
this.state.sessionIdFromServer = this.sessionId;
return yield next
});
客户:
<script>
var sessionId = {{sessionIdFromServer}};
</script>
...
<div id='app'> react app loads here </div>
然后我在我的客户端 HTTP/WebSocket 请求(特别是 websocket)中使用那个 sessionId 变量。
对于客户端发出的每个请求(在套接字的情况下传递 sessionId),服务器在完成请求之前基本上会检查 Redis 会话存储以查看该会话是否仍然有效(即未过期或注销)。
这是 feasible/secure-enough 方法吗?
对,我应该做的就是为你的 session 使用 cookie。这样任何前端 AJAX 调用(包括 WebSocket)都将在请求 headers.
中使用 cookie
在 cookie 上设置 HTTP Only
后,前端 JavaScript 无法修改(或访问)session cookie,但浏览器仍会在任何传出请求。
在我看来,这是使用 session id 最安全的方式,前端不需要首先知道 cookie 的存在。
如果 koa 中的 session 不再存在,您会自动知道用户也已注销。
我为此做了一个小例子(下面有一个Github link):
首先是index.js
:
'use strict';
const session = require('koa-session');
const koa = require('koa');
const websockify = require('koa-websocket');
const route = require('koa-route');
const app = websockify(koa());
app.keys = ['some secret hurr'];
const sessionStore = session(app);
app.use(sessionStore);
app.ws.use(sessionStore);
app.use(route.all('/', function* (next) {
// ignore favicon
if (this.path === '/favicon.ico') return;
let n = this.session.views || 0;
this.session.views = ++n;
yield next;
}));
app.ws.use(route.all('/', function* (next) {
this.websocket.on('message', (message) => {
let n = this.session.views || 0;
this.session.views = ++n;
if (message === 'ping') {
// Return the amount of sessions (n) when the client sends ping
this.websocket.send('pong ' + n);
}
});
yield next;
}));
app.use(require('koa-static')('./public'));
app.listen(3000);
console.log('listening on port 3000');
然后是index.html
:
<html>
<script>
var ws = new WebSocket("ws://localhost:3000/");
ws.onopen = function() {
// Sends a message
ws.send("ping");
};
ws.onmessage = function(e) {
// Receives a message.
alert(e.data);
};
ws.onclose = function() {
alert("closed");
};
</script>
</html>
我已将所有这些放入一个工作示例中 on GitHub。
我有一个从服务器呈现页面的 NodeJS (Koa) 服务器应用程序,即 nunjucks/jade/etc。登录页面也是服务器呈现的。登录后,将创建 cookie。
现在我正在构建一个将嵌入到安全页面中的 React 应用程序(在用户登录后)。让 React 应用程序使用用户当前登录的会话向服务器发出安全 Http/Websocket 请求的最佳方式是什么?
目前,我正在将 sessionId 注入到加载 React 应用程序的服务器呈现页面的脚本标记中。所以...
服务器:
var session = require('koa-generic-session');
app.use(session({
store: redisStore(...)
}));
app.use(function*(next) {
this.state.sessionIdFromServer = this.sessionId;
return yield next
});
客户:
<script>
var sessionId = {{sessionIdFromServer}};
</script>
...
<div id='app'> react app loads here </div>
然后我在我的客户端 HTTP/WebSocket 请求(特别是 websocket)中使用那个 sessionId 变量。
对于客户端发出的每个请求(在套接字的情况下传递 sessionId),服务器在完成请求之前基本上会检查 Redis 会话存储以查看该会话是否仍然有效(即未过期或注销)。
这是 feasible/secure-enough 方法吗?
对,我应该做的就是为你的 session 使用 cookie。这样任何前端 AJAX 调用(包括 WebSocket)都将在请求 headers.
中使用 cookie在 cookie 上设置 HTTP Only
后,前端 JavaScript 无法修改(或访问)session cookie,但浏览器仍会在任何传出请求。
在我看来,这是使用 session id 最安全的方式,前端不需要首先知道 cookie 的存在。
如果 koa 中的 session 不再存在,您会自动知道用户也已注销。
我为此做了一个小例子(下面有一个Github link):
首先是index.js
:
'use strict';
const session = require('koa-session');
const koa = require('koa');
const websockify = require('koa-websocket');
const route = require('koa-route');
const app = websockify(koa());
app.keys = ['some secret hurr'];
const sessionStore = session(app);
app.use(sessionStore);
app.ws.use(sessionStore);
app.use(route.all('/', function* (next) {
// ignore favicon
if (this.path === '/favicon.ico') return;
let n = this.session.views || 0;
this.session.views = ++n;
yield next;
}));
app.ws.use(route.all('/', function* (next) {
this.websocket.on('message', (message) => {
let n = this.session.views || 0;
this.session.views = ++n;
if (message === 'ping') {
// Return the amount of sessions (n) when the client sends ping
this.websocket.send('pong ' + n);
}
});
yield next;
}));
app.use(require('koa-static')('./public'));
app.listen(3000);
console.log('listening on port 3000');
然后是index.html
:
<html>
<script>
var ws = new WebSocket("ws://localhost:3000/");
ws.onopen = function() {
// Sends a message
ws.send("ping");
};
ws.onmessage = function(e) {
// Receives a message.
alert(e.data);
};
ws.onclose = function() {
alert("closed");
};
</script>
</html>
我已将所有这些放入一个工作示例中 on GitHub。