1、cookie是什么
◆存儲在瀏覽器的一段字符串,最大5kb
◆每個域都可有一個cookie , 跨域不共享
◆格式如k1=v1; k2=v2; k3=v3; ( 可結(jié)構(gòu)化)
2、cookie會隨http請求傳遞給服務端
◆每次 http請求, cookie都會隨著傳遞到服務端
◆服務端可修改 cookie再返回給前端
◆默認, 跨域不可傳遞cookie
3、 服務端操作 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)
// // 結(jié)構(gòu)化 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')
4、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'
// // 結(jié)構(gòu)化,koa2 已經(jīng)做好了
})
app.listen(3000)
5、cookie如何用于登錄校驗
◆請求登錄接口,成功則設置cookie,如user=zhangsan
◆前端再請求其他接口,就會帶著上述cookie【同域下】
◆服務端判斷cookie有無 user=zhangsan,即可驗證
6、cookie和session
1、cookie不能暴露用戶名
◆上一節(jié), cookie中有 user = zhangsan
◆cookie 存放用戶信息明文,非常危險
◆解決方案:cookie存一個用戶標識,如userld=123
2、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)
7、Koa2實現(xiàn)登錄
1、安裝插件
koa-generic-session --save
2、在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
}
// 用戶已經(jīng)訪問過了
ctx.session.viewcount++ // 遞增
// 返回
ctx.body = {
title: 'session-test',
viewcount: ctx.session.viewcount
}
})
8、模擬登錄和驗證
// 模擬登錄
router.get('/login-mock', async (ctx, next) => {
let str = ''
const query = ctx.query // url 參數(shù),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 || {}
})
9、完善登錄功能,連接數(shù)據(jù)庫
// 登錄(對接數(shù)據(jù)庫的)
// 為了方便同域的測試,暫用 get 請求
router.get('/login', async (ctx, next) => {
const { username, password } = ctx.query // get 請求
// const { username, password } = ctx.request.body // post 請求
// 查詢數(shù)據(jù)庫
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: '用戶名或密碼錯誤'
}
})
10、登錄驗證的中間件
// 登錄驗證的中間件
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