node.js(express.js)+mysql实现登录功能

发布时间:2024年01月18日


前言

实现步骤

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语句成功,但是获取到的数据条件不等于1
    if (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的前缀
      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语句成功,但是获取到的数据条件不等于1
    if (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语句成功,但是获取到的数据条件不等于1
    if (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语句成功,但是获取到的数据条件不等于1
    if (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的前缀
      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);
});
文章来源:https://blog.csdn.net/weixin_50379372/article/details/135668565
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。