1.session
cookie的问题:
- 暴露username,很危险,同时cookie也小(5kb)
- 如何解决:cookie中存储userid,server端对应 username
- 解决方案:session,即server端存储用户信息
2.session演示
app.jsconst handleBlogRouter = require('./src/router/blog')
const handleUserRouter = require('./src/router/user')
const querystring = require('querystring')
// session 数据
const SESSION_DATA = {}
// 获取 cookie 的过期时间
const getCookieExpires = () => {
const d = new Date()
d.setTime(d.getTime()+ (24*60*60*1000))
return d.toGMTString()
}
...
const serverHandle = (req, res) => {
// 设置返回格式 JSON
res.setHeader('Content-type', 'application/json')
// 获取path
const url = req.url
req.path = url.split('?')[0] // 获取路由
// 解析 query
req.query = querystring.parse(url.split('?')[1])
// 解析cookie
req.cookie = {}
const cookieStr = req.headers.cookie || '' //k1=v1;k2=v2;
cookieStr.split(';').forEach(item => {
if(!item) {
return
}
const arr = item.split('=')
const key = arr[0].trim()
const val = arr[1].trim()
req.cookie[key] = val
})
console.log('req.cookie is',req.cookie)
// 解析 session
let needSetCookie = false //有userId不需设置cookie
let userId = req.cookie.userid
if (userId) {
if(!SESSION_DATA[userId]) {
SESSION_DATA[userId] = {}
}
} else {
needSetCookie = true //没有userId需设置cookie
userId = `${Date.now()}_${Math.random()}`
SESSION_DATA[userId] = {}
}
req.session = SESSION_DATA[userId]
getPostData(req).then(postData => {
req.body = postData
//console.log(postData)
// 处理 blog 路由
// 返回的是promise
const blogResult = handleBlogRouter(req,res)
if (blogResult) {
blogResult.then(blogData => {
// 如果需要设置cookie
if (needSetCookie) {
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
}
res.end(
JSON.stringify(blogData)
)
})
return
}
// 处理 user 路由
const userResult = handleUserRouter(req,res)
if (userResult) {
userResult.then(userData => {
// 如果需要设置cookie
if (needSetCookie) {
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
}
res.end(
JSON.stringify(userData)
)
})
return
}
// 未命中路由返回404
res.writeHead(404, {"Content-type": "text/plain"})
res.write("404 not Found\n")
res.end()
})
}
module.exports = serverHandle
- 设置SESSION_DATA与获取cookie时间函数。
- 解析cookie
- 解析session,let userId = req.cookie.userid;如果userId存在但不存在SESSION_DATA[userId],SESSION_DATA[userId] ={}赋值给req.session,let needSetCookie = false(默认不需要设置cookie,因为传过来的cookie有userid不为空);如果userId不存在, needSetCookie = true(需要设置cookie),userId =
${Date.now()}_${Math.random()}
(随机生成cookie),SESSION_DATA[userId] = {}赋给req.session;如果userId和SESSION_DATA[userId]都存在,req.session = SESSION_DATA[userId],这里的SESSION_DATA[userId]的userId不同,所以req.session会存入所有的userId不同的信息。 - 为处理blog路由和user路由添加如果needSetCookie = true的情况逻辑,即userId不存在时需服务器端设置cookie。
if (needSetCookie) {
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
}
router/user.js
// 登陆
if (method === 'GET' && req.path === '/api/user/login') {
// const {username, password} = req.body
const {username, password} = req.query
const result = login(username, password)
return result.then(data => {
if (data.username) {
// 设置 session
req.session.username = data.username
req.session.realname = data.realname
console.log('req.session is',req.session)
return new SuccessModel()
}
return new ErrorModel('登陆失败')
})
}
// 登陆验证的测试
if (method === 'GET' && req.path === '/api/user/login-test') {
if (req.session.username) {
return Promise.resolve(new SuccessModel({session: req.session}))
}
return Promise.resolve(new ErrorModel('尚未登陆'))
}
- 登陆路由,如果数据库中查询到相应的username和realname,服务器端设置对应的session(req.session)
2.测试登陆路由,如果req.session.username已经存在,就表示已经登陆,不存在表示尚未登陆。
清空cookie测试:
登陆:由于还没有userid,服务器端会进行创建的一系列操作
再验证: