web server博客项目
document.cookie
document.cookie = 'foo=bar;'
只能增加 cookie, 不能删除app.js
// 解析 cookie
req.cookie = {}
const cookieStr = req.headers.cookie || '' // k1=v1; k2=v2; k3=v3
cookieStr.split(';').forEach(item => {
if (!item) {
return
}
const arr = item.split('=')
const key = arr[0]
const val = arr[1]
req.cookie[key] = val
})
console.log('req.cookie is: ', req.cookie)
// 在客户端中 document.cookie = 'username: zhangsan;'
// req.cookie is: { username: 'zhangsan' }
router/user.js
// 登录
if (method === 'GET' && path === '/api/user/login') {
// const {
// username,
// password
// } = req.body
const { username, password } = req.query
const result = login(username, password)
// if (result) {
// return new SuccessModel(result)
// } else {
// return new ErrorModel('登录失败')
// }
return result.then(data => {
if (data.username) {
// 操作 cookie
res.setHeader('Set-Cookie', `username=${data.username}; path=/`)
return new SuccessModel()
}
return new ErrorModel('登录失败')
})
}
// 登录验证测试
if (method === 'GET' && req.path === '/api/user/login-test') {
if (req.cookie.username) {
return Promise.resolve(
new SuccessModel({
username: req.cookie.username
})
)
}
return Promise.reject(
new ErrorModel('登录失败')
)
}
在客户端当你登录成功后 ( username=lisi ) -> 删除 cookie ( username=lisi ) -> 添加 cookie ( username=zhangsan ) 会发现 用张三的账号操作的李四账号
router/user.js
const {
login
} = require('../controller/user')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 获取 cookie 的过期时间
const getCookieExpires = () => {
const d = new Date()
d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
return d.toGMTString() // Mon, 08 Jul 2019 05:27:33 GMT
}
handleUserRouter = (req, res) => {
const {
method,
path
} = req
// 登录
if (method === 'GET' && path === '/api/user/login') {
// const {
// username,
// password
// } = req.body
const { username, password } = req.query
const result = login(username, password)
// if (result) {
// return new SuccessModel(result)
// } else {
// return new ErrorModel('登录失败')
// }
return result.then(data => {
if (data.username) {
// 操作 cookie
res.setHeader('Set-Cookie', `username=${data.username}; path=/; httpOnly; expires=${getCookieExpires()}`)
// path=/ 所有网站都生效
// httpOnly 只允许前端更改
// expires 过期时间
return new SuccessModel()
}
return new ErrorModel('登录失败')
})
}
// 登录验证测试
if (method === 'GET' && req.path === '/api/user/login-test') {
if (req.cookie.username) {
return Promise.resolve(
new SuccessModel({
username: req.cookie.username
})
)
}
return Promise.reject(
new ErrorModel('登录失败')
)
}
}
module.exports = handleUserRouter
// session 数据
const SESSION_DATA = {}
// 获取 cookie 的过期时间
const getCookieExpires = () => {
const d = new Date()
d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
return d.toGMTString() // Mon, 08 Jul 2019 05:27:33 GMT
}
...
// 解析 session
let needSetCookie = false
let userId = req.cookie.userid
if (userId) {
if(!SESSION_DATA[userId]) {
SESSION_DATA[userId] = {}
}
} else {
needSetCookie = true
userId = `${Date.now()}_${Math.random()}`
SESSION_DATA[userId] = {}
}
req.session = SESSION_DATA[userId]
...
// 处理 user 路由
const userResult = handleUserRouter(req, res)
if (userResult) {
userResult.then(userData => {
if (needSetCookie) {
res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
}
res.end(
JSON.stringify(userData)
)
})
return
}
router/user.js
return result.then(data => {
if (data.username) {
// 操作 cookie
res.setHeader('Set-Cookie', `userid=${data.userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
// path=/ 所有网站都生效
// httpOnly 只允许前端更改
// expires 过期时间
// 设置 session
req.session.username = data.username
req.session.realname = data.realname
console.log('req.session is : ', req.session)
return new SuccessModel(req.session)
}
return new ErrorModel('登录失败')
})
}
// 登录验证测试
if (method === 'GET' && req.path === '/api/user/login-test') {
if (req.session.username) {
return Promise.resolve(
new SuccessModel({
username: req.session
})
)
}
return Promise.reject(
new ErrorModel('尚未登陆')
)
}
cnpm i redis -S
const env = process.env.NODE_ENV // 环境参数
// 配置
let MYSQL_CONF
let REDIS_CONF
if (env === 'dev') {
// MySQL
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: 'root',
port: '3306',
database: 'myblog'
}
// redis
REDIS_CONF = {
port: 6379,
host: '127.0.0.1'
}
}
if (env === 'production') {
MYSQL_CONF = {
host: 'localhost',
user: 'root',
password: 'root',
port: '3306',
database: 'myblog'
}
// redis
REDIS_CONF = {
port: 6379,
host: '127.0.0.1'
}
}
module.exports = { MYSQL_CONF, REDIS_CONF }
db/redis.js
const redis = require('redis')
const { REDIS_CONF } = require('../conf/db.js')
// 创建客户端
const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host)
redisClient.on('error', err => {
console.error(err)
})
function set(key, val) {
if (typeof val === 'object') {
val = JSON.stringify(val)
}
redisClient.set(key, val, redis.print)
}
function get(key) {
const promise = new Promise((resolve, reject) => {
redisClient.get(key, (err, val) => {
if (err) {
reject(err)
return
}
if (val == null) {
resolve(null)
return
}
try {
resolve(
JSON.parse(val)
)
} catch (ex) {
resolve(val)
}
})
})
return promise
}
module.exports = {
set,
get
}
const {
getList,
getDetail,
newBlog,
updateBlog,
delBlog
} = require('../controller/blog')
const { SuccessModel, ErrorModel } = require('../model/resModel')
// 统一的登录验证函数
const loginCheck = (req) => {
if (!req.session.username) {
return Promise.resolve(
new ErrorModel('尚未登录')
)
}
}
const handleBlogRouter = (req, res) => {
const method = req.method // GET POST
const id = req.query.id
// 获取博客列表
if (method === 'GET' && req.path === '/api/blog/list') {
let author = req.query.author || ''
const keyword = req.query.keyword || ''
// const listData = getList(author, keyword)
// return new SuccessModel(listData)
if (req.query.isadmin) {
// 管理员界面
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登录
return loginCheckResult
}
// 强制查询自己的博客
author = req.session.username
}
const result = getList(author, keyword)
return result.then(listData => {
return new SuccessModel(listData)
})
}
// 获取博客详情
if (method === 'GET' && req.path === '/api/blog/detail') {
// const data = getDetail(id)
// return new SuccessModel(data)
const result = getDetail(id)
return result.then(data => {
return new SuccessModel(data)
})
}
// 新建一篇博客
if (method === 'POST' && req.path === '/api/blog/new') {
// const data = newBlog(req.body)
// return new SuccessModel(data)
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登录
return loginCheckResult
}
req.body.author = req.session.username
const result = newBlog(req.body)
return result.then(data => {
return new SuccessModel(data)
})
}
// 更新一篇博客
if (method === 'POST' && req.path === '/api/blog/update') {
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登录
return loginCheckResult
}
const result = updateBlog(id, req.body)
return result.then(val => {
if (val) {
return new SuccessModel()
} else {
return new ErrorModel('更新博客失败')
}
})
}
// 删除一篇博客
if (method === 'POST' && req.path === '/api/blog/del') {
const loginCheckResult = loginCheck(req)
if (loginCheckResult) {
// 未登录
return loginCheckResult
}
const author = req.session.username
const result = delBlog(id, author)
return result.then(val => {
if (val) {
return new SuccessModel()
} else {
return new ErrorModel('删除博客失败')
}
})
}
}
module.exports = handleBlogRouter
const { login } = require('../controller/user')
const { SuccessModel, ErrorModel } = require('../model/resModel')
const { set } = require('../db/redis')
const handleUserRouter = (req, res) => {
const method = req.method // GET POST
// 登录
if (method === 'POST' && 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
// 同步到 redis
// console.log(req.session)
set(req.sessionId, req.session)
return new SuccessModel()
}
return new ErrorModel('登录失败')
})
}
}
module.exports = handleUserRouter