cookie和session

[toc]

网站可以保持我们的登录状态。

网站服务器程序可以在浏览器中写入 cookie,然后浏览器再次访问这个网站时,就会带着这个 cookie。

实例代码如下所示

1
2
3
4
router.get("/", async (ctx) => {
ctx.cookies.set("username", "xiaoming");
ctx.body = "hello cookie";
});

可以在 chrome 调试工具中的 network 选项卡查看 cookie 内容

写入 cookie 之后,这个浏览器再次访问这个网站的任何一个页面,都会带着这个 cookie。

通过maxAge可以设置 cookie 过期的毫秒数,实例代码如下所示

1
2
3
ctx.cookies.set("username", "xiaoming", {
maxAge: 5000, //过期时间设置为五秒
});

可以通过下面的方法获取 cookie。

1
2
3
4
router.get("/images", async (ctx) => {
let usr = ctx.cookies.get("username");
ctx.body = usr;
});

记录网页访问次数

利用 cookie,可以记录客户端访问浏览器的次数,实例代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
router.get("/count", async (ctx) => {
let count = ctx.cookies.get("count");
if (count > 0) {
count = ++count;
ctx.cookies.set("count", count, {
maxAge: 2000,
});
} else {
count = 1;
ctx.cookies.set("count", 1);
}
ctx.body = count;
});

session

利用 cookie 在客户端存储数据是完全透明的,如果存储一些用户信息,会导致很严重的安全问题,所以为了记录用户的登录状态,需要使用 cookie 与 session 结合的方式。

1
cnpm install --save koa-session

例如给 session 设置一个 count 属性,可以直接通过赋值的方式

1
ctx.session.count = 0;

获取也可以使用相同的方法

1
let count = ctx.session.count;

记录网页访问次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const session = require("koa-session");
//加密的密钥,服务器通过加密的cookie获取session
app.keys = ["secret"];
app.use(
session(
{
maxAge: 2000,
},
app
)
);

router.get("/session", async (ctx) => {
if (ctx.session.count > 0) {
ctx.session.count = ++ctx.session.count;
} else {
ctx.session.count = 1;
}
ctx.body = ctx.session.count;
});

登录验证

  • 首页:任何人都可以访问
  • 登录页:提供表单,用户可以通过表单输入登录信息。
  • 视频页:登录成功后可查看,并提供注销功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//处理表单
router.post("/login", async (ctx) => {
let username = ctx.request.body.username;
let password = ctx.request.body.password;
if (username == "admin" && password == "123456") {
ctx.session.username = username;
ctx.redirect("/video");
} else {
ctx.redirect("/");
}
});

//视频页
router.get("/video", async (ctx) => {
console.log(ctx.session.username);
if (ctx.session.username) {
await ctx.render("c", { username: ctx.session.username });
} else {
ctx.redirect("/");
}
});
//表单页面
router.get("/login", async (ctx) => {
await ctx.render("index");
});
//注销
router.get("/logout", async (ctx) => {
ctx.session.username = "";
ctx.redirect("/");
});

课后练习

实现晓舟报告的登录功能,要求如下:

  1. 点击登录按钮,跳转至表单页面,输入用户名和密码后即实现登录效果。
  2. 登录后,任何一个页面都可以显示用户名。

server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
const Koa = require("koa");
const router = require("koa-router")();
const views = require("koa-views");
const parser = require("koa-parser");
const nunjucks = require("nunjucks");
const session = require("koa-session");

const app = new Koa();

app.keys = ["123456"];

app.use(
session(
{
maxAge: 30 * 1000,
},
app
)
);

app.use(
views(__dirname + "/views", {
map: {
html: "nunjucks",
},
})
);

app.use(parser());

// 首页 :任何用户都可以访问
router.get("/", async (ctx) => {
let username = ctx.cookies.get("username");
await ctx.render("home.html", {
username,
});
});

// 登录页 :任何用户都可以访问
router.get("/login", async (ctx) => {
let username = ctx.cookies.get("username");
if (username) {
ctx.session.user = "";
ctx.cookies.set("username", "");
}
await ctx.render("login.html");
});

// 内容页 :只有登录成功后才可以访问
router.get("/list", async (ctx) => {
let username = ctx.cookies.get("username");

if (ctx.session.user) {
await ctx.render("list.html", {
username,
});
} else {
ctx.redirect("/");
}
});

router.get("/logout", async (ctx) => {
ctx.session.user = "";
ctx.cookies.set("username", "");
ctx.redirect("/");
});

// 处理请求的路由
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.cookies.set("username", username, {
maxAge: 30 * 1000,
});
// 重定向
ctx.redirect("/list");
} else {
ctx.redirect("/");
}
});

app.use(router.routes());

app.listen(3000, () => {
console.log("server listening on port 3000"); //http://127.0.0.1:3000
});

list.html

1
2
3
{% extends "./views/layout.html"%} {% block content %}
<h1>列表</h1>
{% endblock %}

home.html

1
2
3
{% extends "./views/layout.html"%} {% block content %}
<h1>首页</h1>
{% endblock %}

login.html

1
2
3
4
5
6
7
{% extends "./views/layout.html"%} {% block content %}
<form action="/login" method="post">
<input type="text" name="username" placeholder="username" />
<input type="password" name="password" placeholder="password" />
<input type="submit" value="Login" />
</form>
{% endblock %}

layout.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!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>
<a href="/">首页</a>
<a href="/list">列表</a>
<div style="float:right;">
{% if username %}
<span>{{username}},<a href="/logout">注销</a></span>
{% else %}
<a href="/login">登录</a>
{% endif %}
</div>
{% block content %}{% endblock %}
</body>
</html>

欢迎关注我的其它发布渠道