上一篇用 koa-static 挂了静态资源。这一篇看 Koa 里的 cookie 和 session:HTTP 本身无状态,换一个页面服务器就认不出是不是同一个浏览器,必须靠这两样把访问串起来。
Cookie 存在访问者电脑上,同一浏览器访问同一域名时可以共享数据。Session 存在服务器上:第一次访问时服务器创建 session 对象,把 key 以 cookie 形式发给浏览器,下次带着 key 就能找到对应的 value。
一、设置与读取 Cookie
Koa 内置 cookie API,写法是 ctx.cookies.set / ctx.cookies.get(注意是 cookies,不是 cookie)。中文要先 encodeURIComponent,读出来再 decodeURIComponent,否则「张三」这类汉字传不对。
//引入 koa模块
const Koa = require('koa');
const Router = require('koa-router');
const views = require('koa-views');
const static = require('koa-static');
//实例化
const app = new Koa();
const router = new Router();
//配置静态资源中间件
app.use(static(__dirname + "/static"));
//配置模板引擎中间件
app.use(views('views', {
extension: 'ejs'
}));
router.get('/', async (ctx) => {
// 设置 cookie
ctx.cookies.set('userinfo',encodeURIComponent('张三'),{maxAge:10*1000})
await ctx.render('index', {});
});
router.get('/news', async (ctx) => {
// 获取 cookie
console.log(decodeURIComponent(ctx.cookies.get('userinfo')));
await ctx.render('index', {});
});
//启动路由
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
先访问 localhost:3000 写入 cookie,再访问 localhost:3000/news,控制台就能打出 userinfo = 张三。
第三个参数是选项对象。上面的 maxAge: 10 * 1000 表示存 10 秒,到期消失。常见可选项如下。
| 选项 |
含义 |
| maxAge |
过期时间,毫秒。10 * 1000 即 10 秒 |
| httpOnly |
true 时只有服务器能读 cookie,前端脚本读不到 |
| signed |
是否签名,需配合 app.keys |
| overwrite |
是否允许覆盖已有同名 cookie |
二、koa-session 把状态放服务器
Session 是另一种记客户状态的机制:Cookie 在浏览器,Session 在服务器。第一次请求时服务器创建类似 key/value 的对象,把 key 写回浏览器;下次带着这个 cookie,就能找到对应 session。客户信息保存在 session 里。
npm install koa-session --save
//引入 koa模块
const Koa = require('koa');
const Router = require('koa-router');
const views = require('koa-views');
const static = require('koa-static');
const session = require('koa-session');
//实例化
const app = new Koa();
const router = new Router();
//配置静态资源中间件
app.use(static(__dirname + "/static"));
//配置模板引擎中间件
app.use(views('views', {
extension: 'ejs'
}));
//配置session的中间件
app.keys = ['some secret hurr']; /**cookie的签名 默认*/
const CONFIG = {
key: 'koa:sess', /** 默认 */
maxAge: 10000, /** cookie的过期时间 */
overwrite: true, /** 默认 可以重写过期时间 */
httpOnly: true, /** true表示只有服务器端可以获取 cookie */
signed: true, /** 默认 签名 */
rolling: true, /** 在每次请求时强行设置 cookie,这将重置 cookie 过期时间(默认:false) */
renew: false, /** 当用户进行浏览器操作时刷新 cookie 过期时间 */
};
app.use(session(CONFIG, app));
router.get('/', async (ctx) => {
// 设置 cookie
ctx.session.userinfo='张三';
await ctx.render('index', {});
});
router.get('/news', async (ctx) => {
// 获取 cookie
console.log(ctx.session.userinfo);
await ctx.render('index', {});
});
//启动路由
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
引入 koa-session 后配中间件。日常主要改三个值:
-
-
rolling:每次请求都重写 cookie,从而重置过期时间(默认 false);
-
访问首页时设置 ctx.session.userinfo = '张三',再进 /news 打印,就能拿到「张三」。
三、Cookie 和 Session 怎么选
| 对比 |
Cookie |
Session |
| 存放位置 |
客户浏览器 |
服务器 |
| 安全 |
可被分析、冒用,敏感数据不适合 |
相对更安全 |
| 性能 |
不占服务器内存 |
访问多了占服务器资源 |
| 容量 |
单个不超过 4K,很多浏览器限制约 20 个 |
受服务器存储限制 |
一句话总结:Cookie 用 ctx.cookies 存浏览器(中文要编解码);Session 用 koa-session 存服务器。敏感信息偏向 session,减轻服务器压力则偏向 cookie。