[toc]
cookie 与 session 概述
网站可以保持我们的登录状态。
cookie
网站服务器程序可以在浏览器中写入 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
| 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");
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("/"); });
|
课后练习
实现晓舟报告的登录功能,要求如下:
- 点击登录按钮,跳转至表单页面,输入用户名和密码后即实现登录效果。
- 登录后,任何一个页面都可以显示用户名。
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"); });
|
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>
|