前言:黑夜冷风吹起无聊的思緒,那些伤痕像細雨一样密布身体每个细胞
START-从零到壹
在很久很久以前......,多的不说,少的不唠,咱先创建个文件夹进行初始化再说, npm init -y
,工欲善其事必先利其器,在终端安装好一下工具(express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架,cors 处理跨域请求,mysql数据库,我们使用的是MySQL Workbench 8.0CE)
npm i express@4.17.1
npm i cors@2.8.5
npm i mysql@2.18.1
复制代码
安装好插件后,在根目录创建app.js去开启服务器(先尝试一下最简单的服务器=> 运行方法:在终端输入命令 node .\app.js 即可运行服务器了)
// app.js
const express = require("express")
const app = express()
app.listen(2000,()=>{
console.log('api server running at http://127.0.0.1:2000');
})
复制代码
控制台这样显示就是服务器已经在运行了哈
跨域
通常我们会碰到跨域的问题(出于浏览器的同源策略限制),当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
// 解决跨域
// app.js
const cors=require("cors")
app.use(cors())
// 解析表单数据(只能解析application/x-www-form-urlencoded格式的数据),必须写在路由之前
app.use(express.urlencoded({ extended: false }))
复制代码
路由
我们会在根目录下创建两个文件夹(router,router_handle)在对路由进行分工
// router/user.js
const express = require("express")
const route = express.Router() // 路由的实例化
// 注册用户路由
route.post('/reguser', (req, res) => {
res.send('reguser ok')
})
// 登录用户路由
route.post('/login', (req, res) => {
res.send('login ok')
})
// 将挂载好的路由暴露出去
module.exports = route
复制代码
我们做好以上后,路由还没通呢,需要在app.js中使用该路由
// 导入路由 app.js
const router = require("./router/user")
app.use('/api', router) // 注册并使用,路由地址前缀 /api
复制代码
接下来就可以测试下是否成功(Postman,Apipost这两个工具都可以),我们可以看到返回的结果
抽离对应的路由函数事件,在router_handle/user.js文件中创建事件,并在route中引入使用
// router/user.js
const express = require("express")
const route = express.Router() // 路由的实例化
// 导入抽离路由的事件
const route_handle = require("../router_handle/user")
// 注册用户路由
route.post('/reguser', route_handle.reguser)
// 登录用户路由
route.post('/login', route_handle.login)
// 将挂载好的路由暴露出去
module.exports = route
复制代码
// 注册 router_handle/user.js
exports.reguser = (req, res) => {
res.send('reguser ok')
}
// login
exports.login = (req, res) => {
res.send('login ok')
}
复制代码
MySQL
开启数据库(my_db_02),创建表(ev_users)
表创建成功后,我们需要在根目录下创建一个db文件夹来管理数据库,此前我们已经安装过mysql了
// 引入mysql db/index.js
const mysql = require("mysql")
const db = mysql.createPool({
host: "127.0.0.1",
user: 'root', // mysql用户名
passsword: "123123",// mysql密码
database: "my_db_02" // 数据库
})
module.exports = db
复制代码
数据库准备完毕后,我们在注册的路由事件中去完成校验匹配(在这里我们需要一个插件bcryptjs npm i bcryptjs
进行加密处理)
注册
// 导入数据库 router_handle/user.js
const db = require("../db/index")
// 导入加密处理的插件
const bcryptjs = require("bcryptjs")
// 注册
exports.reguser = (req, res) => {
const userInfo = req.body // 获取请求体的内容
console.log(userInfo, 'userInfo');
// 定义查询用户名的sql语句
let sqlStr = 'select * from ev_users where username=?'
// 使用数据库的查询
db.query(sqlStr, userInfo.username, (err, results) => {
// 验证用户名
if (err) {
return res.send({ status: 1, message: err.message })
}
console.log(results, 'results');
if (results.length > 0) {
return res.send({ status: 1, message: "用户名已被注册" })
}
// 验证密码 (需要安装插件bcryptjs,npm i bcryptjs)
// 存进数据库对密码进行了加密处理
userInfo.password = bcryptjs.hashSync(userInfo.password, 10)
// 定义插入数据的sql
let sqlSet = 'insert into ev_users set ?'
db.query(sqlSet, { username: userInfo.username, password: userInfo.password }, (err, results) => {
if (err) {
return res.send({ status: 1, message: err.message })
}
if (results.affectedRows !== 1) {
return res.send({
status: 1,
message: "注册用户失败,请稍后重试"
})
} else {
res.send({ status: 1, message: "注册成功" })
}
})
})
}
复制代码
验证表单的数据
前端验证为辅,后端验证为主,我们要在后端进行数据的校验尤为重要,在根目录下创建一个文件schema,并安装两个插件( npm i joi @escook/express-joi
)
// 导入定义验证规则包 schema/user.js
const joi = require("joi")
// 定义用户名和密码验证规则
const username = joi.string().alphanum().min(1).max(10).required()
const password = joi.string().pattern(/^[\S]{6,12}$/).required()
// 定义验证注册和登录表单的数据规则对象
exports.reg_login_schema = {
body: {
username,
password
}
}
复制代码
定义好校验后,在router里进行配置
// 导入验证数据的中间件
const expressJoi = require("@escook/express-joi")
// 导入验证的对象
const { reg_login_schema } = require("../schema/user")
// 注册用户路由(路由中间加入校验体)
route.post('/reguser', expressJoi(reg_login_schema), route_handle.reguser)
// 登录用户路由
route.post('/login', expressJoi(reg_login_schema), route_handle.login)
复制代码
然会要在app.js中在路由之后定义错误级别中间件
// 在上边导入joi
const Joi = require("joi")
// 路由之后
app.use((err, req, res, next) => {
if (err instanceof joi.ValidationError) {
return res.send({ status: 1, message: err.message })
}
})
复制代码
登录
登录要验证用户名与密码,登录成功要生成token值,在根目录下新建config.js,生成token的配置文件( npm i jsonwebtoken@8.5.1
)
// 导入token包 config.js
const jwt = require("jsonwebtoken")
const config = require("../config")
复制代码
// router_handle/user.js
exports.login = (req, res) => {
let userInfo = req.body
let sqlLogin = `select * from ev_users where username=?`
db.query(sqlLogin, userInfo.username, (err, results) => {
if (err) {
return res.send({ststus:1,message:err.message})
}
// console.log(results[0], 'results');
if (results.length !== 1) {
return res.send({ststus:1,message:'登录失败'})
}
// 校验传输密码与数据库密码的正确性 (bcrypt.compareSync (用户输入密码,数据库密码))
const isPsd = bcryptjs.compareSync(userInfo.password, results[0].password)
if (!isPsd) {
res.send({ststus:1,message:'登录失败'})
} else {
// 将密码和头像数据置为空进行token的生成
const user = { ...results[0], password: "", user_pic: "" }
// 生成Token
const token = jwt.sign(user, config.jwtSecretKey, { expiresIn: config.expiresIn })
res.send({
status: 0,
message: "登录成功",
token: "Bearer " + token
})
}
})
}
复制代码
ok,可以看到登录账号密码123456时,返回成功并带有token值,数据库中没有账号12345,所以登录失败
解析token的中间件
先安装插件 npm i express-jwt@5.3.3
//引入解析token的插件 (app.js)
const expressJWT = require("express-jwt")
const config = require("./config")
复制代码
要在路由之前配置解析token的插件
app.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/api/] }))
在判断错误级别的中间件中进行判断提示
if (err.name === "UnauthorizedError") return res.cc("认证失败")
以下是验证的情况:
1.登录成功时,拿到token
2.去发起一个随意路径(目前路由只有登录和注册两个)的请求,但不是以/api开头的,因为上面我们已经对/api开头的进行了校验,我们可以看到认证失败
3.把登录成功的token值放在header中带进去,我们可以看到请求认证通过,但是返回error,是因为我们没有当前请求路径
在学习中前行,在激流中涌进。学习笔记。
作者:狂徒张三本尊
链接:https://juejin.cn/post/7122704687559606286
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。