文章目录
- 前言
- 实现步骤
- 实现步骤
- 一、检测登录表单的数据是否合法
- (3)新建schema/user.js
- (4)在routes/use.js中引入schema/user.js中的方法reg_login_schema,代码如下:
- 二、根据用户名查询用户的数据
- 三、判断用户输入的密码是否正确
- 四、生成JWT 的 Token 字符串
- 最终登录接口代码如下:
- 五、在app.js中注册路由之前,配置解析token的中间件,为了指定那些接口不需要进行Token 的身份认证
前言
实现步骤
1.检测表单数据是否合法
2.根据用户名查询用户的数据
3.判断用户输入的密码是否正确
4.生成JWT 的 Token 字符串
登录接口完整代码如下:controllers/user.js文件
// 登录接口
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// 判断密码是否和数据库中的密码是否一致// compareSync 第一个参数用户输入的,第二个参数数据库查询到的// 返回值为ture 一致,反之const compareResult = bcrypt.compareSync(userinfo.password,results[0].password);console.log("1", userinfo.password);console.log("2", results[0].password);if (!compareResult) {return res.cc("登录失败233");}// 生成jwt的token字符串// 清空用户信息的密码和头像const user = { ...results[0], password: "", user_pic: "" };console.log(user);// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: "10h", // token 有效期为10小时});// 将生成的token字符串响应给客户端res.send({status: 0,message: "登录成功!",// 为了方便客户端使用,在服务器端直接拼接上Bearer的前缀// 注意:Bearer 后面必须有空格token: "Bearer "+ tokenStr,});// res.cc("ok");});
};
实现步骤
一、检测登录表单的数据是否合法
1)安装 jOi 包,为表单中携带的每个数据项,定义验证规则:
npm install joi
(2)安装 @escook/express-j01 中间件,来实现自动对表单数据进行验证的功能:
npm install @escook/express-joi
(3)新建schema/user.js
// 导入定义验证规则的包
// const joi = require("@hapi/joi");
const joi = require("joi");
/*** string()值必须是字符串* alphanum()值只能包含a-zA-ZO-9的字符串* min(length) 最小长度* max(length) 大长度* required() 值是必填项,不能为 undefined* pattern(正则表达式) 值必须符合正则表达式的规则*/// 定义用户名和密码的验证规则
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,},
};
(4)在routes/use.js中引入schema/user.js中的方法reg_login_schema,代码如下:
var express = require("express");
var router = express.Router();
// 引入封装的获取验证码的方法
var unr_handler = require("../controllers/user");// 1.导入验证数据的中间件
const expressJoi = require("@escook/express-joi");
// 2.导入需要的验证规则对象
const { reg_login_schema } = require("../schema/user");// 新用户注册
// router.post("/regUser", expressJoi(reg_login_schema), unr_handler.regUser);
// router.post("/regUser", unr_handler.regUser);
// 登录
router.post("/login", expressJoi(reg_login_schema), unr_handler.login);
module.exports = router;
二、根据用户名查询用户的数据
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
// 登录接口
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// res.cc("ok");});
};
三、判断用户输入的密码是否正确
// 导入密码加密
const bcrypt = require("bcryptjs");
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// 判断密码是否和数据库中的密码是否一致// compareSync 第一个参数用户输入的,第二个参数数据库查询到的// 返回值为ture 一致,反之const compareResult = bcrypt.compareSync(userinfo.password,results[0].password);console.log("1", userinfo.password);console.log("2", results[0].password);if (!compareResult) {return res.cc("登录失败233");}// res.cc("ok");});
};
四、生成JWT 的 Token 字符串
1)在生成 Token 字符串的时候,一定要别除 密码 和 头像 的值
// 清空用户信息的密码和头像const user = { ...results[0], password: "", user_pic: "" };
2)安装成成token的字符串包
npm 1 jsonwebtoken@8.5.1
3)在 /controllers/user.js 模块的头部区域,导入 jsonwebtoken 包:
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
4)创建 config.js 文件,并向外共享加密和还原Token 的 jwtSecretKey 字符串:
// 全局的配置文件
module.exports = {// 加密和解密 token 的密钥jwtSecretKey: "itheima No1. ^_^",
};
5)将用户信息对象加密成 Token 字符串, 在controllers/user.js文件引入config.js
// 导入密钥
const config = require("../config");
const user = { ...results[0], password: "", user_pic: "" };console.log(user);// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: "10h", // token 有效期为10小时});// 将生成的token字符串响应给客户端res.send({status: 0,message: "登录成功!",// 为了方便客户端使用,在服务器端直接拼接上Bearer的前缀token: "Bearer"+ tokenStr,});
最终登录接口代码如下:
// 登录接口
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
exports.login = (req, res) => {// 获取客户端提交到服务器的用户信息const userinfo = req.body;// 定义sql语句,根据用户名查询用户的信息const sql = `select * from ev_users where username=?`;// 执行sql语句,根据用户名查询用户的信息db.query(sql, userinfo.username, (err, results) => {// 执行sql语句失败if (err) return res.cc(err);// 执行sql语句成功,但是获取到的数据条件不等于1if (results.length !== 1) return res.cc("登录失败!");// 判断密码是否和数据库中的密码是否一致// compareSync 第一个参数用户输入的,第二个参数数据库查询到的// 返回值为ture 一致,反之const compareResult = bcrypt.compareSync(userinfo.password,results[0].password);console.log("1", userinfo.password);console.log("2", results[0].password);if (!compareResult) {return res.cc("登录失败233");}// 生成jwt的token字符串// 清空用户信息的密码和头像const user = { ...results[0], password: "", user_pic: "" };console.log(user);// 对用户的信息进行加密,生成token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: "10h", // token 有效期为10小时});// 将生成的token字符串响应给客户端res.send({status: 0,message: "登录成功!",// 为了方便客户端使用,在服务器端直接拼接上Bearer的前缀// 注意:Bearer 后面必须有空格token: "Bearer "+ tokenStr,});// res.cc("ok");});
};
/utils/db文件代码
const mysql = require("mysql");
const db = mysql.createPool({host: "localhost", // 连接地址port: "3306", //端口号user: "root", //用户名password: "XXXXXXX", //密码database: "exapp2", //数据库名
});
module.exports = db;
五、在app.js中注册路由之前,配置解析token的中间件,为了指定那些接口不需要进行Token 的身份认证
1.安装解析 Token 的中间件:
npm i express-jwt@5.3.3
2). app.js
// 导入配置文件
const config = require("./config");
// 解析token的中间件
const expressJWT = require("express-jwt");
// 使用 unless({ path:[/^\/user\//] )) 指定哪些接口不需要进行 Token 的身份认证
// ps: path: [/^\/user/] 改成你自己的接口前缀path: [/^\/XXX/]
app.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/user/] })
);
3)在 app.js 中的 错误级别中间件 里面,捕获并处理 Token 认证失败后的错误:
// 定义表单验证失败的错误的中间件,并把验证失败的结果响应给客户端
// 错误中间件
app.use(function (err, req, res, next) {// 数据验证失败,instanceof判断if (err instanceof joi.ValidationError) {return res.cc(err);}// token身份认证失败后的错误if (err.name === "UnauthorizedError") return res.cc("身份认证失败");// 未知错误res.cc(err);
});