实现思路
- 前端传过来用户的用户名和密码
- 对用户名密码进行合法性校验
- 根据用户名在 m y s q l mysql mysql数据库中查找用户相关信息
- 将查询到的密码解码后与传过来的密码比对
- 比对成功,生成token字符串返回给前端
项目目录
--api_server
--db
--index.js
-- node_modules
--router
--user.js
-- router_handler
-- user.js
-- schema
--user.js
-- config.js
-- app.js
代码编写
在router
文件夹中的 user.js
中配置之前封装好的 joiExpress
中间件
// ./router/user.js
// 登录路由
router.post('/login', joiExpress, userHandler.login)
// ./router_handler/user.js
// 登录路由处理函数
const login = (req, res) => {
const { username, password } = req.body
//ev_users为用户表表名 , ? 是占位符
let sql = `select * from ev_users where username=?`
// 查询用户数据 , username是传到占位符?处的数据
db.query(sql, [username], (err, result) => {
if (err) return res.cc(err)
if (result.length !== 1 ) return res.cc('找不到该用户!')
})
}
接下来要取出密码并解码
// 登录路由处理函数
const login = (req, res) => {
const { username, password } = req.body
let sql = `select * from ev_users where username=?`
// 查询用户数据
db.query(sql, [username], (err, result) => {
if (err) return res.cc(err)
if (result.length !== 1 ) return res.cc('找不到该用户!')
// 进行密码比对
if (bcrypt.compareSync(password, result[0].password)) {
} else {
res.cc('用户名或密码错误~')
}
})
}
密码匹配成功后,我们需要给前端返回一个token用于身份认证。
这里先说说 JWT
。
由于Cookie
不支持跨域访问,当前端跨域请求后端接口要做很多的额外配置,因此就有了 JWT
,即 JSON Web Token
,它是一个跨域认证解决方案,原理是将用户信息加密生成 Token
字符串存储在 Local Storage
或Session Storage
,当再次请求有权限的接口时,需要在请求头部带上 Authorization
字段发送 token
。该字段的一般格式是 Authorization: Bearer <token>
,其中Bearer
表示遵守 OAuth2.0
规则。
我们使用第三方包 jsonwebtoken
来生成JWT
字符串
jwt.sign(负载, 自定义密钥, { 有效时间 })
负载和有效时间单独写在 config.js
里
// ./config.js
// 定义密钥
const jwtSecretKey = 'dianzan'
// token有效期
const expiresIn = '1h'
module.exports = {
jwtSecretKey,
expiresIn
}
// ./router_handler/user.js
// 导入token密钥和有效时间
const { jwtSecretKey, expiresIn } = require('../config')
// 导入jsonwebtoken包用于生成token
let jwt = require('jsonwebtoken')
// 登录路由处理函数
const login = (req, res) => {
const { username, password } = req.body
let sql = `select * from ev_users where username=?`
// 查询用户数据
db.query(sql, [username], (err, result) => {
if (err) return res.cc(err)
if (result.length !== 1 ) return res.cc('找不到该用户!')
// 进行密码比对
if (bcrypt.compareSync(password, result[0].password)) {
// 定义负载,密码不要作为负载,把它设置为空,user_pic为用户头像,太大也不要作负载
const user = { ...result[0], password: '', user_pic: '' }
// 生成token
let token = jwt.sign(user, jwtSecretKey, { expiresIn })
res.send({ status: 0, message: '登录成功~', token: 'Bearer ' + token })
} else {
res.cc('用户名或密码错误~')
}
})
}
在路由前使用第三方中间件 express-jwt
来解析token字符串
// ./app.js
// 导入解析token的中间件express-jwt
const expressJwt = require('express-jwt')
// 使用中间件解析token
app.use(expressJwt({ secret: config.jwtSecretKey, algorithms: ['HS256'] }).unless({ path: [/^\/api/] }))
// 使用路由
app.use('/api', userRouter)