Cookie
HTTP请求是无状态的,但是在开发时,有些情况是需要知道请求的人是谁的。为了解决这个问题,HTTP协议设计了一个特殊的请求头:Cookie。服务端可以通过响应头(set-cookie)将少量数据响应给客户端,浏览器会遵循协议将数据保留,并在下一次请求同一个服务的时候带上。
// html中插入DOM和JS方法
<div><button onclick="add()">增加Cookie</button><button onclick="del()">删除Cookie</button><button onclick="editor()">修改Cookie</button><button onclick="show()">查看Cookie</button>
</div>
<script>function add(){fetch("/add",{method:"post",headers:{"Content-type":"application/json"}});}function del(){fetch("/del",{method:"post",headers:{"Content-type":"application/json"}});}function editor(){fetch("/editor",{method:"post",headers:{"Content-type":"application/json"}});}function show(){fetch("/show",{method:"post",headers:{"Content-type":"application/json"}});}
</script>
async add() {const ctx = this.ctxctx.cookies.set("user", "jspang.com")ctx.body = {status:200,data:'Cookie添加成功'}
}
async del() {const ctx = this.ctxctx.cookies.set("user", null)ctx.body = {status:200,data:'Cookie删除成功'}
}
async editor() {const ctx = this.ctxctx.cookies.set("user",'bilibili')ctx.body = {status:200,data:'Cookie修改成功'}
}
async show() {const ctx = this.ctxconst user=ctx.cookies.get("user")console.log(user)ctx.body = {status:200,data:'Cookie显示成功'}
}// 配置路由
router.post('/add', controller.zhuba.add);
router.post('/del', controller.zhuba.del);
router.post('/editor', controller.zhuba.editor);
router.post('/show', controller.zhuba.show);
配置和加密
一些配置选项,比如有效时间、服务端操作设置和中文编写加密这些操作。
ctx.cookies.set( ) 方法是有三个参数的,第一个参数是key,第二个参数是value,第三个参数就可以进行配置。比如你需要配置Cookie的有效时间,可以使用maxAge属性。(这个时间是毫秒。)
maxAge 时效设置
maxAge: 1000 * 2 (毫秒)
async add(){const ctx = this.ctxctx.cookies.set("user","jspang.com",{maxAge:1000*2})ctx.body = {status:200,data:'Cookie添加成功'}
}
HhttpOnly 是否只允许服务端来操作Cookie
伪造Cookie来绕过登录是黑客经常使用的一种手段,所以为了安全,Egg.js默认设置只允许服务端来操作Cookie。
比如通过JS的方式document.cookie获取Cookie是不能获取的(需要在浏览器的控制台输入获取)。当我们想通过客户端操作Cookie时,可以通过下面的代码进行设置。
async add(){const ctx = this.ctxctx.cookies.set("user","jspang.com",{maxAge:1000*60,httpOnly:false})ctx.body = {status:200,data:'Cookie添加成功'}
}
encrypt 设置中文Cookie (set加密 show解密)
加密只要在第三个参数中,加入encrypt:true,就可以加密成功。
ctx.cookies.set("user","zhuba",{encrypt:true
})
直接通过ctx.cookies.get( )方法获取,获取的是undefind,也就是无法获取的。这时候需要再次配置解密才可以使用, 在show( )方法里配置代码如下。
const user=ctx.cookies.get("user",{encrypt:true
})
Session
Cookie和Session非常类似,Egg中的Session就存储再Cookie中,但是Session比Cookie的安全性更高。所以在开发中经常使用Cookie来保存是否登录,而用Session来保存登录信息和用户信息。
添加、获取、删除
- 添加:在add()方法中 ctx.session.username = ‘zhuba’
- 获取:直接获取 const username = ctx.session.username
- 删除:把值赋为空即可 ctx.session.username = null
session是支持中文的,不需要加密解密
配置项
config.session = {key :"PANG_SESS", // 设置Key的默认值httpOnly:true, // 设置服务端操作maxAge:1000*60 , // 设置最大有效时间renew: true, // 页面有访问动作自动刷新session
}
中间件的编写
Egg是对Koa的二次封装,所以中间件这部分和Koa框架是一样的,也追寻洋葱圈模型。
Egg.js约定中间件要写在/app/middleware文件夹下
module.exports = options => {return async (ctx, next) => {if (ctx.session.counter) { // 没学数据库先使用sessionctx.session.counter++;} else {ctx.session.counter = 1;}await next();}
};
手动挂载:config/config.default.js config.middleware = [‘counter’];
在index()中使用, 可以发现中间件现在的作用域是全局的。
要想只在某一页面使用需要在router(路由)中配置中间件的使用,并去除全局挂载。
const counter = app.middleware.counter()const {router,controller,} = app;router.get('/', counter, controller.home.index);
在实际开发中中间件还是有很多用处的,比如日志的记录、比如所有页面的Gzip压缩展示、比如全局埋点的使用