cookie是什么
◆存储在浏览器的一段字符串,最大5kb
◆每个域都可有一个cookie , 跨域不共享
◆格式如k1=v1; k2=v2; k3=v3; ( 可结构化)
cookie会随http请求传递给服务端
◆每次 http请求, cookie都会随着传递到服务端
◆服务端可修改 cookie再返回给前端
◆默认, 跨域不可传递cookie
服务端操作 cookie
代码示例:
// 服务端操作 cookie
const http = require('http')
const server = http.createServer((req, res) => {
// 设置 cookie
res.setHeader('Set-Cookie', 'c=200')
// 获取 cookie
const cookieStr = req.headers.cookie
console.log('cookie is ', cookieStr)
// // 结构化 cookie(概念很重要)
// cookieStr: 'a=100; b=200' --> { a: '100', b: '200' }
const cookieObj = {}
cookieStr.split(';').forEach(cookieItemStr => {
const arr = cookieItemStr.trim().split('=')
const key = arr[0] // 'a'
const val = arr[1] // '100'
cookieObj[key] = val
})
console.log('cookie obj is', cookieObj)
res.end('cookie test')
})
server.listen(3000)
console.log('server listening on 3000 port')
Koa2设置或者获取cookie
// Koa2 操作 cookie
const Koa = require('koa')
const app = new Koa()
app.use(async (ctx) => {
// 设置 cookie
ctx.cookies.set('a', '500')
// 获取 cookie
console.log('cookie is', ctx.cookies.get('a'))
ctx.body = 'cookie test by Koa2'
// // 结构化,koa2 已经做好了
})
app.listen(3000)
cookie如何用于登录校验
- 请求登录接口,成功则设置cookie,如user=zhangsan
- 前端再请求其他接口,就会带着上述cookie【同域下】
- 服务端判断cookie有无 user=zhangsan,即可验证
cookie和session
cookie不能暴露用户名
- 上一节, cookie中有 user = zhangsan
- cookie 存放用户信息明文,非常危险
- 解决方案:cookie存一个用户标识,如userld=123
session是什么
- cookie 存储用户标识,如userId
- 用户信息则存储到session中
- session 即用户信息的存储,和cookie有对应关系
模拟 session 它是一个全局对象,它的key就是用户标识,它的value就是存储的用户信息
session简单的小例子:
// Koa2 操作 cookie
const Koa = require('koa')
const app = new Koa()
// 模拟 session
const SESSION_DATA = {
'123': {
user: 'zhangsan',
age: 20
},
'456': {
user: 'lisi'
},
'789': {
user: 'shuangyue'
}
}
app.use(async (ctx) => {
// 加入用户登录成功,服务端设置 cookie (userId ,不能泄露用户信息)
ctx.cookies.set('userId', '123')
// 其他接口,获取 cookie
const userId = ctx.cookies.get('userId')
const userInfo = SESSION_DATA[userId]
userInfo.user // 用户名
ctx.body = 'cookie test by Koa2'
})
app.listen(3000)
Koa2实现登录
- 安装插件
koa-generic-session --save
- 在app.js文件中引入和配置
引入
const session = require('koa-generic-session')
配置
app.keys = ['wertwe^&&*UUI123123'] // 秘钥
// 自定配置了 cookie 和 session
app.use(session({
// 配置 cookie
cookie: {
path: '/', // cookie 在根目录下有效
httpOnly: true, // cookie 只允许服务端来操作
maxAge: 24 * 60 * 60 * 1000 // cookie 的过期时间
}
}))
- 定义路由:router/index.js
router.get('/session-test', async (ctx, next) => {
// ctx.session
if (ctx.session.viewcount == null) {
// 用户尚未访问
ctx.session.viewcount = 0
}
// 用户已经访问过了
ctx.session.viewcount++ // 递增
// 返回
ctx.body = {
title: 'session-test',
viewcount: ctx.session.viewcount
}
})
- 模拟登录和验证
// 模拟登录
router.get('/login-mock', async (ctx, next) => {
let str = ''
const query = ctx.query // url 参数,querystring
if (query.username) {
// 模拟登录成功
ctx.session.userInfo = {
username: query.username
}
str = 'login ok'
} else {
// 模拟登录失败,不用处理 session
str = 'login failed'
}
ctx.body = str
})
// 模拟登录验证
router.get('/login-check-mock', async (ctx, next) => {
ctx.body = ctx.session.userInfo || {}
})
- 完善登录功能,连接数据库
// 登录(对接数据库的)
// 为了方便同域的测试,暂用 get 请求
router.get('/login', async (ctx, next) => {
const { username, password } = ctx.query // get 请求
// const { username, password } = ctx.request.body // post 请求
// 查询数据库
const user = await User.findOne({
username,
password
})
if (user != null) {
// 登录成功,设置 session
ctx.session.userInfo = user // 所有的用户信息
// 返回
ctx.body = {
errno: 0,
data: user
}
return
}
// 登录失败,不用操作 session
ctx.body = {
errno: -1,
message: '用户名或密码错误'
}
})
- 登录验证的中间件
// 登录验证的中间件
async function loginCheck (ctx, next) {
const userInfo = ctx.session.userInfo
if (userInfo && userInfo.username) {
// 登录验证成功
await next()
return
}
// 登录失败
ctx.body = {
errno: -1,
message: '请登录'
}
}
module.exports = loginCheck