基于koa与nunjucks实现cookie与session
# 一、cookie 与 session概述
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确认用户身份,Session通过在服务端记录信息确认用户身份。
在用户登陆一个网站时候,网站通常会保持登陆状态持续一定的时间,这个就是会话跟踪技术的应用之一。
# 二、Cookie
Cookie是服务端发给客户端的凭证,不需要服务器记录;
Session是服务端存储的关于确认客户端的凭证,客户端的Cookie是用来验证客户端的真实性。
网站服务器程序可以在浏览器中写入cookie,然后浏览器再次访问这个网站时,就会带着这个cookie;示例代码为以koa框架创建的web服务器:
router.get('/', async ctx => {
// cookie是以明值对的方式记录在客户端(浏览器)的
ctx.cookies.set('username', 'simonzhangs')
ctx.body = 'cookie'
})
2
3
4
5
6
写入cookie之后,这个浏览器再次访问这个网站的任何一个页面,都会带着这个cookie。
可以通过下面方法获取cookie:
router.get('/test', async ctx => {
let username = ctx.cookies.get('username')
ctx.body = username;
})
2
3
4
通过maxAge
可以设置cookie过期的毫秒数:
ctx.cookies.set('username', 'simonzhangs', {
maxAge: 5000
})
2
3
通过cookie来记录网页访问量:
router.get('/test', async ctx => {
let count = ctx.cookies.get('count');
if(count) {
++count;
ctx.cookies.set('count', count);
} else {
count = 1;
ctx.cookies.set('count', 1);
}
ctx.body = count;
})
2
3
4
5
6
7
8
9
10
11
# 三、Session
利用cookie在客户端存储数据是明值对、完全透明的,如果存储一些用户信息,会导致很严重的安全问题,所以为了记录用户的登陆状态,需要使用cookie与session结合的方式。
利用koa的中间件koa-session: npm i --save koa-session
;
引入并使用:
const session = require('koa-session') //引入
// 配置使用
const app = new Koa();
app.keys = ['123456']
app.use(session({
maxAge:10000,
}, app))
2
3
4
5
6
7
8
设置session:
router.get('/session', async ctx => {
ctx.session.username = 'admin';
ctx.body = 'set session';
})
2
3
4
获取session:
router.get('/session_test', async ctx => {
let username = ctx.session.username;
ctx.body = username;
})
2
3
4
在设置session时,session内容保存在服务端,同时发送cookie到客户端,这个cookie是一串密钥,用于在请求服务端数据时对用户身份的确认。
同样可以利用session来记录网页访问次数:
router.get('./session', async ctx => {
if(ctx.session.count) {
ctx.session.count++;
} else {
ctx.session.count = 1;
}
ctx.body = ctx.session.count;
})
2
3
4
5
6
7
8
# 四、登陆验证
利用koa与nunjucks实现session与cookie结合来模拟用户登陆过程,要求能达到:
- 首页:任何用户都可以访问;
- 登陆页:任何用户都可以访问;
- 未登录时,为登陆表单;
- 登录后,提示已登陆成功;
- 内容页:只有登陆成功后才可以访问;
- 注销:登陆后可以选择注销;
- 登陆后,任何一个页面都可以显示用户名。
首先安装项目所用依赖包,并在server.js中引入并使用:
const Koa = require('koa');
const views = require('koa-views');
const router = require('koa-router')()
const nunjucks = require('nunjucks')
const parser = require('koa-parser')
const session = require('koa-session')
const app = new Koa();
// session密钥及seesion使用
app.keys = ['123456']
app.use(session({
maxAge:30*1000,
}, app));
// koa的post请求内容解析
app.use(parser());
// nunjucks 页面模板路径配置
app.use(views(__dirname + '/views', {
map:{html: 'nunjucks'}
}))
// 页面路由
app.use(router.routes())
app.listen(3000, () => {
console.log('server is running');
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
然后在views文件夹下,新建需要用的页面:
- 公共页面部分:layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<a href="/">首页</a>
<a href="/list">列表</a>
<a href="/login">登陆</a>
</div>
{% block content %}
{% endblock %}
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 首页:home.html
{% extends './views/layout.html' %}
{% block content %}
<h1>首页</h1>
<p>Hello,{{user}}</p>
{% endblock %}
2
3
4
5
- 登陆页面:login.html
{% extends './views/layout.html' %}
{% block content %}
{% if isLogin %}
<p>您已经登陆!! {{isLogin}} </p>
{% else %}
<form action="/login" method="post">
<input type="text" name="username" id="">
<input type="password" name="password" id="">
<input type="submit" value="登录">
</form>
{% endif %}
{% endblock %}
2
3
4
5
6
7
8
9
10
11
12
4.登陆后才可以访问的页面:list.html
{% extends './views/layout.html' %}
{% block content %}
<h1>列表</h1>
<p>Hello,{{user}}</p>
<a href="/logout">注销</a>
{% endblock %}
2
3
4
5
6
然后在server.js中配置路由信息和逻辑:
// 首页:任何用户都可以访问
router.get('/', async ctx => {
let user = ctx.session.user
await ctx.render('home.html',{
user
})
})
2
3
4
5
6
7
//登陆页:任何用户都可以访问,表单
router.get('/login', async ctx => {
let isLogin = false;
if(ctx.session.user){
isLogin = true;
}
await ctx.render('login.html', {
isLogin
});
})
2
3
4
5
6
7
8
9
10
//登陆页表单post
router.post('/login', async ctx => {
let username = ctx.request.body.username;
let password = ctx.request.body.password;
if (username === 'admin' && password === '123456') {
ctx.session.user = 'admin'
// 重定向
ctx.redirect('./list');
} else {
ctx.redirect('/')
}
})
2
3
4
5
6
7
8
9
10
11
12
// 内容页:只有登陆成功后才可以访问
router.get('/list', async ctx => {
if (ctx.session.user) {
let user = ctx.session.user
await ctx.render('list.html',{
user
});
}else {
ctx.redirect('/');
}
})
2
3
4
5
6
7
8
9
10
11
// 注销
router.get('/logout', async ctx => {
ctx.session.user = '';
ctx.redirect('/');
})
2
3
4
5