• Node编写用户登录接口


    目录

    前言

    服务器

    编写登录接口API

    使用sql语句查询数据库中是否有该用户

    判断密码是否正确

    生成JWT的Token字符串

    配置解析token的中间件

    配置捕获错误中间件

    完整的登录接口代码


    前言

    本文介绍如何使用node编写登录接口以及解密生成token,如何编写注册接口已经在Node编写用户注册接口这篇文章中介绍,本文是建立在编写注册接口这篇文章的基础之上

    同时也可以在在前端html页面中向服务器发送post登录请求这篇文章中了解登录请求

    服务器

    关于创建服务器,本文中和Node编写用户注册接口共用一个服务器,已经引入了router对象

    1. // 导入express模块
    2. const express = require('express')
    3. // 创建express服务器实例
    4. const app = express()
    5. // 导入跨域cors
    6. const cors = require('cors')
    7. // 全局挂载
    8. app.use(cors())
    9. // 配置解析表单数据中间件
    10. app.use(express.urlencoded({extended:false}))
    11. // 导入用户路由对象
    12. const userRouter = require('./router/user')
    13. app.use('/api',userRouter)
    14. // 启动服务器
    15. app.listen(3007,()=> {
    16. console.log('running the http://127.0.0.1:3007');
    17. })

    编写登录接口API

    使用sql语句查询数据库中是否有该用户
    1. const userinfo = req.body
    2. const sql = 'select * from ev_users where username = ?'
    3. db.query(sql, userinfo.username, function (err, results) {
    4. // 执行 SQL 语句失败
    5. if (err) {
    6. return res.send({status:1,message:err.message})
    7. }
    8. // 执行 SQL 语句成功,但是查询到数据条数不等于 1
    9. if (results.length !== 1) {
    10. return res.send({status:1,message:'登录失败'})
    11. }
    12. res.send('登录成功')
    13. })

    使用postman模拟发送登录请求,查询是否有用户名为b

    返回登录成功

    数据库中有b用户

    如果未注册

    数据库中没有c用户

    判断密码是否正确

    调用了bcrypt.compareSync()方法,用来解密,因为在注册时已经把密码加密了,所以需要解密

    bcrypt.compareSync(用户提交的密码,数据库中的密码)

    1. // 判断密码是否正确
    2. const compareResult = bcrypt.compareSync(userinfo.password,results[0].password)
    3. if(!compareResult) return res.send({status:1,message:'密码错误'})
    4. res.send('登录成功')

    验证b的密码是否正确

    b的密码是000000

    当把b的密码换成111111时,也就是错误密码

    返回密码错误

    生成JWT的Token字符串

    关于JWT认证,可以浏览JWT认证这篇文章

    生成token字符串时,要把密码和用户头像剔除,因为生成的token会保留在浏览器中,很容易泄露

    1. // 剔除完毕之后,user 中只保留了用户的 id, username, nickname, email 这四个属性的值
    2. const user = { ...results[0], password: '', user_pic: '' }

    先安装jsonwebtoken

    npm i jsonwebtoken

    导入jwt

    const jwt = require('jsonwebtoken')

    导入成功后调用jwt.sign()生成JWT字符串

    jwt.sign(用户的信息,加密的密钥,配置对象有效token的时间)

    1. // 生成 Token 字符串
    2. const tokenStr = jwt.sign(user, jwtSecreKey, {
    3. expiresIn: '10h', // token 有效期为 10 个小时
    4. })

    将生成的token字符串发送给客户端

    在生成的的token字符串前拼接上"Bearer",固定用法

    1. res.send({
    2. status: 0,
    3. message: '登录成功!',
    4. // 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀
    5. token: 'Bearer ' + tokenStr,
    6. })

    使用postman模拟发送请求

    配置解析token的中间件

    将jwt字符串还原为JSON对象,在get请求时,可以获得用户信息

    安装express-jwt

    npm i express-jwt

    导入

    1. / 导入解析token字符串
    2. const exoressjwt = require('express-jwt')

    解析token

    1. // 使用 .unless({ path: [/^\/api\//] }) 指定哪些接口不需要进行 Token 的身份认证
    2. app.use(expressjwt.expressjwt({
    3. secret:jwtSecreKey,
    4. algorithms:['HS256'],
    5. }).unless({path:[/^\/api\//]}))
    配置捕获错误中间件
    1. // 错误中间件
    2. app.use(function (err, req, res, next) {
    3. // 捕获身份认证失败的错误
    4. if (err.name === 'UnauthorizedError') return res.send({satus:1,message:'身份认证失败'})
    5. // 未知错误
    6. res.send({status:1,message:err.message})
    7. })

    完整的登录接口代码

    1. // 导入express模块
    2. const express = require('express')
    3. // 导入数据库对象
    4. const db = require('../db/index')
    5. // 导入加密模块
    6. const bcrypt = require('bcryptjs')
    7. // 创建路由对象
    8. const router = express.Router()
    9. // 导入JWT
    10. const jwt = require('jsonwebtoken')
    11. // 定义密钥
    12. const jwtSecreKey = 'notbald'
    13. // 登录接口
    14. router.post('/login',(req,res)=>{
    15. const userinfo = req.body
    16. const sql = 'select * from ev_users where username = ?'
    17. db.query(sql, userinfo.username, function (err, results) {
    18. // 执行 SQL 语句失败
    19. if (err) {
    20. return res.send({status:1,message:err.message})
    21. }
    22. // 执行 SQL 语句成功,但是查询到数据条数不等于 1
    23. if (results.length !== 1) {
    24. return res.send({status:1,message:'登录失败'})
    25. }
    26. // 判断密码是否正确
    27. const compareResult = bcrypt.compareSync(userinfo.password,results[0].password)
    28. if(!compareResult) return res.send({status:1,message:'密码错误'})
    29. // 生成token字符串,展开运算符,剔除密码和用户头像
    30. const user = {...results[0],password:'',user_pic:''}
    31. // console.log(user);
    32. // 生成 Token 字符串
    33. const tokenStr = jwt.sign(user, jwtSecreKey, {
    34. expiresIn: '10h', // token 有效期为 10 个小时
    35. })
    36. res.send({
    37. status: 0,
    38. message: '登录成功!',
    39. // 为了方便客户端使用 Token,在服务器端直接拼接上 Bearer 的前缀
    40. token: 'Bearer ' + tokenStr,
    41. })
    42. })
    43. })

    解析token以及全局捕获错误中间件在服务器中

  • 相关阅读:
    systemd的unit配置文件详解
    IDEA实现远程Debug调试
    LVS: ambighouse pin count in file “xx“ but none has xx pins问题
    从零开始的Django框架入门到实战教程(内含实战实例) - 10 初试Ajax之订单界面(学习笔记)
    【408专项篇】C语言笔记-第七章(函数)
    基于Springboot+vue的学生毕业离校系统 elementui
    蓝桥杯 第 3 场算法双周赛4,7题
    git-命令行显示当前目录分支
    第十章 Watch侦听器
    SpringBoot统一返回值与actuator的矛盾
  • 原文地址:https://blog.csdn.net/weixin_68854196/article/details/133999499