需求背景
设计实现
- 安装 cookie-session 中间件
npm install cookie-session
复制代码
- 使用 cookie-session 中间件
app.use(cookieSession({
name: 'js_session_id',
keys: ['rbac'],
// maxAge: 24 * 60 * 60 * 1000 // 24 hours
}));
复制代码
解读:
- 请求到来时,获取 cookie 中 js_session_id 的值,这个值就是真正的 session_id。
Cookie:js_session_id=eyJpc0xvZ2dlZCI6dHJ1ZX0=;
复制代码
- 根据 session_id 获取服务器内存中获取 session 信息。
- 根据 session 信息判断用户是否已经登录。
注释:
- 如果请求头中没有 cookie,
- 或者 cookie 中找不到 js_session_id 字段,
- 或者根据 session_id (eyJpc0xvZ2dlZCI6dHJ1ZX0=) 找不到与之对应的 session
都代表没有登录。
案例说明
客户端发起请求/sciences-member,请求被中间件 checkLogin 拦截。如果已经登录,那么继续执行下面的逻辑。
router.get(
"/sciences-member", checkLogin, async function (req: Request, res: Response) {
...
res.status(200).send(formatResult(data));
}
);
复制代码
checkLogin 中间件的逻辑很简单。判断 session 是否存在,并且 isLogged 是否为真。
function checkLogin(req: Request, res: Response, next: NextFunction) {
if (req.session && req.session.isLogged) {
next();
} else {
res.status(401).send(formatResult("CheckSessionLogin", "没有登录"));
}
}
复制代码
isLogged 的值是在登录成功时动态添加到 session 对象上去的。
router.post("/login", function (req: Request, res: Response) {
const username = req.body.username;
const password = req.body.password;
if (username === "luohao" && password === "123") {
req.session && (req.session.isLogged = true);
res.status(200).send(formatResult("登录成功"));
} else {
res.status(500).send(formatResult(null, "用户名或者密码错误"));
}
});
复制代码
在 checkLogin 中间件执行的逻辑中,假设不满足已经登录的条件,服务器返回 401 状态码。
前端最好能针对 401 状态码统一处理一下。
instance.interceptors.response.use(
function (response) {
return response.data;
},
function (error) {
// 重新登录
if (error.response.status === 401) {
return (window.location.href = "http://localhost:8088/index.html");
}
return Promise.reject(error.response.data);
}
);
复制代码
注意事项
由于跨域是不可避免的。在跨域的情况下,出于安全性的考虑,XHR 不允许请求携带 cookie 信息。如果不做特殊处理,那么所有请求始终是以未登录的状态发起。为了能够在请求头中携带cookie,需要客户端和服务端协作。
- 客户端配置
const instance = axios.create({
...
withCredentials: true, // 表示跨域请求时是否需要使用凭证
...
});
复制代码
- 服务端配置
res.header("Access-Control-Allow-Credentials", "true");
复制代码




近期评论