# 注册,登录与鉴权
# 1 注册
- 数据库定义model
- 后端写api 处理数据的储存与res; 对密码加密
- 前端post数据到指定的api
# 2 登录
- 根据 req.body的username 找password;
- 校验密码, 使用(bcrypt) 比较req的密码与找到的密码
- 判断密码, 不符合重新登录, 符合返回token
- 返回token,(jsonwebtoken)生成token , 参数(选取用户传入的数据, 后端的密匙字段);
- 全局错误处理函数, 统一处理让前后端都可以
app.post('/admin/api/login', async (req, res) => {
const { username, password } = req.body
// 1.根据用户名找用户
const user = await AdminUser.findOne({ username }).select('+password')
assert(user, 422, '用户不存在')
// 2.校验密码
const isValid = require('bcrypt').compareSync(password, user.password)
assert(isValid, 422, '密码错误')
// 3.返回token
const token = jwt.sign({ id: user._id }, app.get('secret'))
res.send({ token })
})
// 错误处理函数
app.use(async (err, req, res, next) => {
// console.log(err)
res.status(err.statusCode || 500).send({
message: err.message
})
})
# 3 鉴权
需要登录才能访问资源, req.headers每次请求带token, 后端鉴定token的真实性。
后端鉴权中间件
module.exports = options => {
const assert = require('http-assert')
const jwt = require('jsonwebtoken')
const AdminUser = require('../models/AdminUser')
return async (req, res, next) => {
const token = String(req.headers.authorization || '').split(' ').pop()
assert(token, 401, '请先登录')
// secret 是加密生成token时的密匙,
const { id } = jwt.verify(token, req.app.get('secret'))
assert(id, 401, '请先登录')
req.user = await AdminUser.findById(id)
assert(req.user, 401, '请先登录')
await next()
}
}
- axios前端请求, 每次请求自动加上token.
http.interceptors.request.use(function (config) {
// Do something before request is sent
if (localStorage.token) {
config.headers.Authorization = 'Bearer ' + localStorage.token
}
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
# 4 错误处理
- 前后端约定接口和状态
- 前端req 错误处理
- 后端res错误处理
- 前端res错误处理
前端req 错误处理
http.interceptors.request.use(function (config) {
// Do something before request is sent
if (localStorage.token) {
config.headers.Authorization = 'Bearer ' + localStorage.token
}
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
后端res错误处理
app.use(async (err, req, res, next) => {
// console.log(err)
res.status(err.statusCode || 500).send({
message: err.message
})
})
前端res错误处理
http.interceptors.response.use(res => {
return res
}, err => {
if (err.response.data.message) {
Vue.prototype.$message({
type: 'error',
message: err.response.data.message
})
if (err.response.status === 401) {
router.push('/login')
}
}
return Promise.reject(err)
})