前言

我是歌谣 今天继续给大家带来登录鉴权JWT模块的讲解

安装

npm i jsonwebtoken 安装依赖

后台mongoDb

前端歌谣-第柒拾贰课-登录鉴权-JWT鉴权_ios

前端目录

前端歌谣-第柒拾贰课-登录鉴权-JWT鉴权_json_02

usercontroll.js

const UserService = require("../services/UserService")
const JWT = require("../util/jwt")

const UserController = {
    addUser: async (req, res, next) => {
        const { username, password, age } = req.body
        await UserService.addUserService(username, password, age)
        //插入数据库
        res.send({
            ok: 1
        })
    },
    updateUser: async (req, res, next) => {
        const { username, age, password } = req.body
        await UserService.updateUserService(req.params.id, req.params.username, req.params.age, req.params.password)
        res.send({
            ok: 1
        })
    },
    deleteUser: async (req, res, next) => {
        const { username, age, password } = req.body
        await UserService.deleteUserService(req.params.id)
        res.send({
            ok: 1
        })
    },
    getUser: async (req, res) => {
        const { username, age, password }
            = req.body
        let data = await UserService.getUserSerice()
        res.send(data)
    },
    Login: async (req, res) => {
        const { username, password }
            = req.body
        let data = await UserService.loginService(username, password)

        if (data.length == 0) {
            res.send({
                ok: 0
            })
        } else {
            // req.session.user=data[0] //设置
            const token = JWT.generate({
                _id: data[0].id,
                username: data[0].username
            }, "1h")
            console.log(token, "token is")
            //
            res.header("Authorization", token)
            res.send({
                ok: 1
            })
        }
    },
    Logout: (req, res) => {
        // req.session.destroy(() => {
            res.send({ ok: 1 })
        // })
    }
}
module.exports = UserController

userService.js

const UserModel = require("../model/UserModel")

const UserService = {
    addUserService: (username, password, age) => {
        return UserModel.create({
            username, password, age
        }).then(data => {
            console.log(data)
        })
    },
    updateUserService: (_id, username, age, password) => {
        return UserModel.updateOne({ _id: _id }, { username }).then(data => {
            console.log(data)
        })
    },
    deleteUserService: (_id) => {
        return UserModel.deleteOne({ _id: req.params.id }).then(data => {
            console.log(data)
        })
    },
    getUserSerice() {
        return UserModel.find({}, ["username", "age"]).sort({ age: -1 })
    },
    loginService:(username,password)=>{
        return UserModel.find({username,password})
    }
}
module.exports = UserService

login.ejs

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<script>
    axios.interceptors.request.use(function (config) {
        // 在发送请求之前做些什么
        return config;
    }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
    });

    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 2xx 范围内的状态码都会触发该函数。
        // 对响应数据做点什么
        console.log(response.headers,"data is")
        const {authorization}=response.headers
        authorization&&localStorage.setItem("token",authorization)
        return response;
    }, function (error) {
        // 超出 2xx 范围的状态码都会触发该函数。
        // 对响应错误做点什么
        return Promise.reject(error);
    });
</script>

<body>
    <h1>登录页面</h1>
    <div>
        <div>用户名:<input id="username" name="username"></div>
        <div>密码:<input id="password" name="password" type="password"></div>
        <div><input value="登录" id="login" type="submit"></div>
    </div>
    <script>
        var username = document.querySelector("#username")
        var password = document.querySelector("#password")
        var login = document.querySelector("#login")
        login.onclick = function () {
            console.log(username.value, password.value)
            // fetch("/api/login", {
            //     method: "POST",
            //     body: JSON.stringify({
            //         username: username.value,
            //         password: password.value,
            //     }),
            //     headers: {
            //         "Content-type": "application/json"
            //     }
            // }).then(res => res.json()).then(res => {
            //     console.log(res)
            //     if(res.ok===1){
            //         //存储token值

            //         location.href="/"
            //     }else{
            //         console.log("用户名和密码不匹配")
            //     }
            // })
            axios.post("/api/login", { username: username.value, password: password.value, }).then(res => {
                console.log(res, "data is")
                if (res.data.ok === 1) {
                    //存储token值
                    location.href = "/"
                } else {
                    console.log("用户名和密码不匹配")
                }
            })
        }
    </script>
</body>

</html>

index.ejs

<!DOCTYPE html>
<html>

<head>
  <title>
    <%= title %>
  </title>
  <link rel='stylesheet' href='/stylesheets/style.css' />
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script>
    axios.interceptors.request.use(function (config) {
      // 在发送请求之前做些什么
      const token = localStorage.getItem("token")
      config.headers.Authorization = `Bearer ${token}`
      return config;
    }, function (error) {
      // 对请求错误做些什么
      console.log(error.response.status, "111")

      return Promise.reject(error);
    });
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
      // 2xx 范围内的状态码都会触发该函数。
      // 对响应数据做点什么
      console.log(response.headers, "data is")
      const { authorization } = response.headers
      authorization && localStorage.setItem("token", authorization)
      return response;
    }, function (error) {
      // 超出 2xx 范围的状态码都会触发该函数。
      // 对响应错误做点什么
      if (error.response.status === 401) {
        localStorage.removeItem("token")
        location.href = "/login"
      }
      return Promise.reject(error);
    });


  </script>
</head>

<body>
  <h1>
    后台系统用户管理功能
    <button id="exit">退出</button>
  </h1>
  <div>
    <div>用户名:<input id="username" /></div>
    <div>密码:<input type="password" id="password" /></div>
    <div>年龄:<input type="number" id="age" /></div>
    <div><button id="register">添加用户</button></div>
  </div>
  <hr>
  <div><button id="update">更新用户</button>
    <button id="remove">删除用户</button>
  </div>
  <hr>
  <table border="1">
    <thead>
      <tr>
        <td>id</td>
        <td>用户名</td>
        <td>年龄</td>
      </tr>
    </thead>
    <tbody>

    </tbody>
  </table>
  <script>
    var username = document.querySelector("#username")
    var password = document.querySelector("#password")
    var age = document.querySelector("#age")
    var register = document.querySelector("#register")
    var update = document.querySelector("#update")
    var remove = document.querySelector("#remove")
    var exit = document.querySelector("#exit")
    register.onclick = function () {
      console.log(username.value, password.value, age.value)
      // fetch("/api/user", {
      //   method: "POST",
      //   body: JSON.stringify({
      //     username: username.value,
      //     password: password.value,
      //     age: age.value
      //   }),
      //   headers: {
      //     "Content-type": "application/json"
      //   }
      // }).then(res => res.json()).then(res => {
      //   if (res.ok === 0) {
      //     location.href = "/login"
      //   } else {
      //     listUpdate()
      //   }
      // })
      axios.post("/api/user", { username: username.value, password: password.value, age: age.value }).then(res => {
        console.log(res)
        listUpdate()
        // if (res.data.ok === 1) {
        //     //存储token值
        //     location.href = "/"
        // } else {
        //     console.log("用户名和密码不匹配")
        // }
      })
    }
    update.onclick = function () {
      console.log(username.value, password.value, age.value)
      // fetch("/api/user/65406b27f49dbc6f3034f8d0", {
      //   method: "PUT",
      //   body: JSON.stringify({
      //     username: username.value,
      //     password: password.value,
      //     age: "1"
      //   }),
      //   headers: {
      //     "Content-type": "application/json"
      //   }
      // }).then(res => res.json()).then(res => {
      //   if (res.ok === 0) {
      //     location.href = "/login"
      //   } else {
      //     listUpdate()
      //   }
      // })
      axios.put("/api/user/65406b27f49dbc6f3034f8d0", { username: username.value, password: password.value, age: age.value }).then(res => {
        console.log(res)
        listUpdate()
        // if (res.data.ok === 1) {
        //     //存储token值
        //     location.href = "/"
        // } else {
        //     console.log("用户名和密码不匹配")
        // }
      })
    }
    remove.onclick = function () {
      console.log(username.value, password.value, age.value)
      // fetch("/api/user/65406b27f49dbc6f3034f8d0", {
      //   method: "DELETE"
      // }).
      //   then(res => res.json()).then(res => {
      //     if (res.ok === 0) {
      //       location.href = "/login"
      //     } else {
      //       listUpdate()
      //     }

      //   })
      axios.delete("/api/user/65406b27f49dbc6f3034f8d0").then(res => {
        console.log(res)
        listUpdate()
        // if (res.data.ok === 1) {
        //     //存储token值
        //     location.href = "/"
        // } else {
        //     console.log("用户名和密码不匹配")
        // }
      })
    }
    exit.onclick = function () {
      // fetch("/api/logout").
      //   then(res => res.json()).then(res => {
      //     if (res.ok === 1) {
      //       location.href = "/login"
      //     }
      //   })
      axios.get("/api/logout").then(res => {
        console.log(res)
        localStorage.removeItem("token")
        location.href = "/login"
        // if (res.data.ok === 1) {
        //     //存储token值
        //     location.href = "/"
        // } else {
        //     console.log("用户名和密码不匹配")
        // }
      })
    }
    function listUpdate() {
      // fetch("/api/user").then(res => res.json()).then(res => {
      // console.log(res)
      // var tbody = document.querySelector("tbody")
      // tbody.innerHTML = res && res.map(item => `
      // <tr>
      //   <td>${item._id}</td>
      //   <td>${item.username}</td>
      //   <td>${item.age}</td>
      //   </tr>
      // `).join("")
      // })
      axios.get("/api/user").then(res => {
        console.log(res)
        var tbody = document.querySelector("tbody")
        tbody.innerHTML = res.data && res.data.map(item => `
      <tr>
        <td>${item._id}</td>
        <td>${item.username}</td>
        <td>${item.age}</td>
        </tr>
      `).join("")
        // if (res.data.ok === 1) {
        //     //存储token值
        //     location.href = "/"
        // } else {
        //     console.log("用户名和密码不匹配")
        // }
      })
    }
    listUpdate()

  </script>
</body>

</html>

app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require("express-session")
var mongoStore = require("connect-mongo")
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var loginRouter = require('./routes/login');
const JWT = require("./util/jwt")
var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// app.use(session({
//   name:"geyaosystem",
//   secret:"dashini",
//   cookie:{
//     maxAge:1000*60*60,
//     secure:false
//   },
//   resave:true,
//   saveUninitialized:true,
//   store:mongoStore.create({
//     mongoUrl:'mongodb://127.0.0.1:27017/geyao_session',
//     ttl:1000*60*60
//   })
// }))
//设置中间件
// app.use((req,res,next)=>{
//   if(req.url.includes("login")){
//     next()
//     return
//   }
//   if(req.session.user){
//     req.session.mydata=Date.now()
//     next()
//   }else{
//     req.url.includes("api")?res.status(401).send({ok:0}):
//     res.redirect("/login")
//   }
// })
app.use((req, res, next) => {
  if (req.url.includes("login")) {
    next()
    return
  }
  const token = req.headers["authorization"]?.split(" ")[1]
  console.log(token,"token is")
  if (token) {
    const payload = JWT.verify(token)
    if (payload) {
      const newToken=JWT.generate({
        _id:payload._id,
        username:payload.username
      },"1d")
      res.header("Authorization",newToken)
      next()
    } else {
      res.status(401).send({ errCode: -1, errInfo: "token过期" })
    }
  } else {
    next()
  }

})



app.use('/', indexRouter);
app.use('/api', usersRouter);
app.use('/login', loginRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

配置文件

{
  "name": "myapp",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "connect-mongo": "^5.1.0",
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "express-session": "^1.17.3",
    "http-errors": "~1.6.3",
    "jsonwebtoken": "^9.0.2",
    "mongoose": "^7.6.3",
    "morgan": "~1.9.1"
  }
}

运行结果

前端歌谣-第柒拾贰课-登录鉴权-JWT鉴权_ios_03

前端歌谣-第柒拾贰课-登录鉴权-JWT鉴权_用户名_04

token清空刷星

前端歌谣-第柒拾贰课-登录鉴权-JWT鉴权_ios_05

前端歌谣-第柒拾贰课-登录鉴权-JWT鉴权_json_06