node.js(第七章)登录鉴权的方式一Cookie&Session

1. Cookie&Session

「HTTP 无状态」 我们知道, HTTP 是无状态的。也就是说, HTTP 请求方和响应方间无法维护状态, 都是一次性的,它不知道前后的请求都发生了什么。但有的场景下,我们需要维护状态。最典型的,一 个用户登陆CSDN,发布、关注、评论,都应是在登录后的用户状态下的。「标记」那解决办法是什么 呢?

 1.下载插件 

npm i express-session // 操作session
npm i connect-mongo // 将动态的session存到MongoDB的数据库中

2.在app.js中写代码

//引入session
var session = require('express-session')
const MongoStore = require("connect-mongo");

// 注册session中间件
app.use(session({
  name: "xiaogong",  // 名字
  secret: "xiaogongxinhaiganyukeqing", // 秘钥
  cookie: {
    maxAge: 1000 * 60 * 60, // maxAge表示cookie有效时间
    secure:false // secure为 true 时候表示只有 https 协议才能访问cookie
  },
  resave: true, // 重新设置session后,会自动重新计算过期时间
  saveUninitialized: true, // 先给一个无效cookie
  store: MongoStore.create({
    mongoUrl: 'mongodb://127.0.0.1:27017/user_session', // 新创建一个数据库存用户session
    ttl: 1000 * 60 * 10 // session有效时间
  })
}))

// 设置中间件,session过期校验
app.use((req, res, next) => {
  //排除login相关的路由和接口
  if (req.url.includes("login")) {
    next()
    return
  }

  if (req.session.user) {
    // 重新设置session
    req.session.date=Date.now()
    next()
  } else {
    // 是接口返回错误码,不是接口就重定向
    req.url.includes("api")?res.status(401).json({ok:0}):res.redirect('/login')
  }
})

注意:注册和设置中间件要在你创建的路由前面,否则就白写了

 3.在routes文件夹里创建user.js文件,写代码

var express = require('express')
const UserController = require('../controller/UserController')
var router = express.Router()

//登录
router.post('/login', UserController.login)

// 退出登录
router.get('/logout',UserController.logout)

module.exports = router

4.在controller文件夹中创建文件UserController.js文件,写代码

const UserService=require('../service/UserService')
const UserController= {
  login: async (req, res)=> {
    const { username, password } = req.body
    const data = await UserService.login(username, password)
    if (data.length === 0) {
       res.send({
          ok:0
        })
     } else {
      // 设置session对象
       req.session.user=data[0]
       res.send({
         ok: 1
       })
     }
  },
  logout: (req, res) => {
    req.session.destroy(() => {
      res.send({
        ok:1
      })
    })
  }
}

module.exports=UserController

 5.创建model文件夹,创建文件UserModel.js,写代码

const mongoose = require('mongoose')
// 设置字段类型
const Schema=mongoose.Schema
const UserType = {
  username: String,
  password: String,
  age:Number
}

// 模型 user 将会对应 users 集合
const UserModel = mongoose.model("user",new Schema(UserType))

module.exports=UserModel

6.创建service文件夹,创建文件UserService.js,写代码

// 操作数据库
const UserModel=require('../model/UserModel')
const UserService = {
  login: (username,password) => {
    return UserModel.find({username,password})
  }
}

module.exports=UserService

前端login.ejs

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

<head>
  <title></title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
  <div>
    <div>用户名:<input type="text" id="username"></div>
    <div>密码:<input type="password" id="password"></div>
    <button id="login">登录</button>
  </div>

  <script>
    var username = document.querySelector('#username')
    var password = document.querySelector('#password')
    var loginFun = document.querySelector('#login')
    //登录
    loginFun.onclick = () => {
      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 => {
        if (res.ok === 1) {
          location.href = '/'
        } else {
          alert('密码错误!')
        }
      })
    }
  </script>
</body>

</html>

index.ejs

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div>
    <h1>mongodb增删改查</h1>
    <div>
      <div>用户名:<input type="text" id="username"></div>
      <div>密码:<input type="password" id="password"></div>
      <div>年龄:<input type="number" id="age"></div>
      <button id="logout">退出登录</button>
    </div>
    <button id="register">注册</button>
    <hr>
    <button id="update">更新</button>
    <hr>
    <button id="delete">删除</button>
    <hr>
    <button id="search">查询</button>
  </div>
  <script>
    var username = document.querySelector('#username')
    var password = document.querySelector('#password')
    var age = document.querySelector('#age')
    var registerFun = document.querySelector('#register')
    var updateFun = document.querySelector('#update')
    var deleteFun = document.querySelector('#delete')
    var searchFun = document.querySelector('#search')
    var logoutFun = document.querySelector('#logout')

    // 增
    registerFun.onclick = () => {
      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 => {
        console.log(res);
      })
    }

    // 删
    deleteFun.onclick = () => {
      fetch("/api/user/62e748d9332656d2c168621d", {
        method: "DELETE",
      }).then(res => res.json()).then(res => {
        console.log(res);
      })
    }

    // 改
    updateFun.onclick = () => {
      fetch("/api/user/62e748d9332656d2c168621d", {
        method: "PUT",
        body: JSON.stringify({
          username: "宵宫",
          password: "密码",
          age: 1,
        }),
        headers: {
          "Content-Type": "application/json"
        }
      }).then(res => res.json()).then(res => {
        console.log(res);
      })
    }

    // 查
    searchFun.onclick = () => {
      fetch("/api/user/?page=1&limit=2", {
        method: 'GET'
      }).then(res => res.json()).then(res => {
        console.log(res);
      })
    }

    // 退出登录
    logoutFun.onclick = () => {
      fetch("api/logout", {
        method: "GET"
      }).then(res => res.json()).then(res => {
        if (res.ok === 1) {
          location.href = "/login"
        }
      })
    }
  </script>
</body>

</html>

测试: 

没登录时,会有一个没有用的cookie,此时直接在地址栏进http://localhost:3000是进不去的,会被直接重定向到http://localhost:3000/login

 登录之后,会发现数据库会自动新建一个新的数据库user_session,存的数据expires就是session的有效期,刷新页面,session的有效期也会改变,这样用户在登录状态时只要访问接口,就不会使session失效。

 Cookie&Session的缺点:用户数据过多有可能会使数据库崩溃,不同数据库之间的session难以共享。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微光无限

破晓的日子还有很多!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值