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.ctx
ctx.cookies.set("user", "jspang.com")
ctx.body = {
status:200,
data:'Cookie添加成功'
}
}
async del() {
const ctx = this.ctx
ctx.cookies.set("user", null)
ctx.body = {
status:200,
data:'Cookie删除成功'
}
}
async editor() {
const ctx = this.ctx
ctx.cookies.set("user",'bilibili')
ctx.body = {
status:200,
data:'Cookie修改成功'
}
}
async show() {
const ctx = this.ctx
const 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.ctx
ctx.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.ctx
ctx.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) { // 没学数据库先使用session
ctx.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压缩展示、比如全局埋点的使用