nodejs+mongodb筆記------第六章(cookie與session、數(shù)據(jù)加密)

cookie

關(guān)于cookie
1.是什么?
    本質(zhì)就是一個(gè)字符串,里面包含著瀏覽器和服務(wù)器溝通的信息(交互時(shí)產(chǎn)生的信息)。
    存儲(chǔ)的形式以:key-value的形式存儲(chǔ)。
    瀏覽器會(huì)自動(dòng)攜帶該網(wǎng)站的cookie,只要是該網(wǎng)站下的cookie,全部攜帶。
2.分類:
      --會(huì)話cookie(關(guān)閉瀏覽器后,會(huì)話cookie會(huì)自動(dòng)消失,會(huì)話cookie存儲(chǔ)在瀏覽器運(yùn)行的那塊內(nèi)存上)。
      --持久化cookie:(看過期時(shí)間,一旦到了過期時(shí)間,自動(dòng)銷毀,存儲(chǔ)在用戶的硬盤上,備注:如果沒有到過期時(shí)間,同時(shí)用戶清理了緩存,持久化cookie也會(huì)消失)。
3.工作原理:(例子中的小紙條)
      --當(dāng)瀏覽器第一次請求服務(wù)器的時(shí)候,服務(wù)器可能返回一個(gè)或多個(gè)cookie給瀏覽器
      --瀏覽器判斷以下cookie種類
          --會(huì)話cookie:存儲(chǔ)在瀏覽器運(yùn)行的那塊內(nèi)存上
          --持久化cookie:存儲(chǔ)在用戶的硬盤上
      --以后請求該網(wǎng)站的時(shí)候,自動(dòng)攜帶上該網(wǎng)站的所有cookie(無法進(jìn)行干預(yù))
      --服務(wù)器拿到之前自己“種”下cookie,分析里面的內(nèi)容,校驗(yàn)cookie的合法性,根據(jù)cookie里保存的內(nèi)容,進(jìn)行具體的業(yè)務(wù)邏輯。
 4.應(yīng)用:
      解決http無狀態(tài)的問題(例子:7天免登錄,一般來說不會(huì)單獨(dú)使用cookie,一般配合后臺(tái)的session存儲(chǔ)使用)
 5.不同的語言、不同的后端架構(gòu)cookie的具體語法是不一樣的,但是cookie原理和工作過程是不變的。
    備注:cookie不一定只由服務(wù)器生成,前端同樣可以生成cookie,但是前端生成的cookie幾乎沒有意義。
let express = require('express')
let cookieParser = require('cookie-parser')

let app = express()
app.disable('x-powered-by')
app.use(express.static('public'))
//使用cookie-parser,解析瀏覽器攜帶過來的cookie為為一個(gè)對象,隨后掛載到request上
app.use(cookieParser())

//“種”cookie
app.get('/test1',(request,response)=>{
  /*
  * 當(dāng)訪問test1路由時(shí)會(huì)給客戶端“種”一個(gè)cookie
  * 在express中給客戶端“種”一個(gè)cookie,不用借助任何第三方庫
  * */

  //給客戶端“種”下一個(gè)會(huì)話cookie
  //response.cookie('demo',123)

  //給客戶端“種”下一個(gè)持久化cookie
  response.cookie('demo',123,{maxAge:30 * 1000})
  response.send('<h2>我給你種下了一個(gè)cookie,你快看看</h2>')
})
//“讀”cookie
app.get('/test2',(request,response)=>{
  /*
  * 當(dāng)訪問test2時(shí),會(huì)獲取到瀏覽器攜帶過來的cookie
  * 在express中更方便的獲取客戶端攜帶過來的cookie,要借助一個(gè)中間件,名字:cookie-parser
  * */
  console.log(request.cookies)
  const {demo} = request.cookies
  console.log(demo)
  response.send('<h2>我讀到了你攜帶過來的cookies</h2>')
})
//“刪”cookie
app.get('/test3',(request,response)=>{

  //第一種刪除方式:
  //response.cookie('demo','',{maxAge:0})

  //第二種刪除方式:
  response.clearCookie('demo')

  response.send('我刪除了cookie')
})

//4.綁定端口監(jiān)聽
app.listen(3000,(err)=>{
  if (!err) console.log('服務(wù)器啟動(dòng)成功了!')
  else console.log(err)
})

登錄注冊(加入cookie)

db/index.js

/*
* 該模塊用于連接數(shù)據(jù)庫,暴露出去一個(gè)Promise實(shí)例
* 如果連接成功了,Promise實(shí)例內(nèi)部狀態(tài)切換為成功
* 如果連接失敗了,Promise實(shí)例內(nèi)部狀態(tài)切換為失敗
* */
//引入mongoose
let mongoose = require('mongoose')
mongoose.set('useCreateIndex',true)
//定義數(shù)據(jù)庫名
const DB_NAME = 'test'
//定義數(shù)據(jù)庫地址
const DB_URL = 'localhost:27017'
//構(gòu)建一個(gè)Promise實(shí)例,用于管理數(shù)據(jù)庫連接
module.exports = new Promise((resolve,reject)=>{
  //2.連接數(shù)據(jù)庫
  mongoose.connect(`mongodb://${DB_URL}/${DB_NAME}`,{useNewUrlParser:true })

  //3.監(jiān)聽連接狀態(tài)
  mongoose.connection.on('open',(err)=>{
    if(!err){
      console.log(`位于${DB_URL}上的${DB_NAME}數(shù)據(jù)庫連接成功`)
      resolve()
    }else{
      reject(err)
    }
  })
})

model/userModel.js

/*
* 該模塊主要負(fù)責(zé)創(chuàng)建學(xué)生模型
* */
let mongoose = require('mongoose')
//操作數(shù)據(jù)庫
//1.請來一個(gè)保安 ------- 引入約束Schema
let Schema = mongoose.Schema

//2.制定一個(gè)進(jìn)入你家的規(guī)則 -------- 創(chuàng)建一個(gè)約束對象實(shí)例
let userSchema = new Schema({
  email:{
    type:String,
    required:true,
    unique:true
  },
  nick_name:{
    type:String,
    required:true,
  },
  password:{
    type:String,
    required:true,
  },
  date:{
    type:Date,
    default:Date.now()
  },
  enable_flag:{
    type:String,
    default:'Y'
  }
})

/*3.告訴保安你的規(guī)則 ------- 創(chuàng)建模型對象
第一個(gè)參數(shù)與數(shù)據(jù)庫中的集合相對應(yīng),第二個(gè)參數(shù)指定約束對象實(shí)例
只要生成了模型對象,就可以進(jìn)行數(shù)據(jù)的:增刪改查*/
module.exports = mongoose.model('users',userSchema)

router/businessRouter.js

/*
* 該模塊是業(yè)務(wù)路由器,目前管理的業(yè)務(wù)有:登錄、注冊
* */

let {Router} = require('express')

//引入用戶模型
let userModel = require('../model/userModel')

let router = new Router()

//業(yè)務(wù)路由----注冊
router.post('/register',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,nick_name,password,re_password} = request.body
  //2.校驗(yàn)數(shù)據(jù)的合法性
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const nickNameReg = /[\u4e00-\u9fa5]/gm
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  //定義一個(gè)收集錯(cuò)誤信息的對象
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!nickNameReg.test(nick_name)){
    // response.send('昵稱輸入不合法,昵稱應(yīng)為中文')
    // return
    errMsg.nickNameErr = '昵稱輸入不合法,昵稱應(yīng)為中文'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  if(password !== re_password){
    // response.send('兩次輸入密碼不一致')
    // return
    errMsg.rePasswordErr = '兩次輸入密碼不一致'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    //若果進(jìn)入該判斷,意味著用戶輸入的數(shù)據(jù)存在不合法的
    response.render('register',{errMsg})
    return
  }

  //try里面放可能出現(xiàn)錯(cuò)誤的代碼,一旦出現(xiàn)錯(cuò)誤,會(huì)攜帶著錯(cuò)誤信息來到catch中。
  try{
    //3.檢查該郵箱是否注冊過
    let finResult = await userModel.findOne({email})
    if(finResult){
      //response.send(`注冊失敗,${email}郵箱已經(jīng)被注冊了`)
      //return
      errMsg.emailErr = `注冊失敗,${email}郵箱已經(jīng)被注冊了`
      response.render('register',{errMsg})
    }else{
      await userModel.create({email,nick_name,password})
      console.log(`郵箱為:${email},昵稱為:${nick_name}的用戶注冊成功了!`)
      //response.send('注冊成功了!')
      response.redirect(`/login?email=${email}`)
    }
  }
  catch(err){
    //1.計(jì)數(shù) 2.引入警報(bào)模塊
    console.log(err)
    errMsg.networkErr = `阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!`
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('register',{errMsg})
  }
})

//業(yè)務(wù)路由 ---登錄
router.post('/login',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,password} = request.body
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    response.render('login',{errMsg})
    return
  }

  try{
    let findResult = await userModel.findOne({email,password})
    if(findResult){
      //response.redirect(`/usercenter?nick_name=${findResult.nick_name}`)
      //response.render('usercenter',{nickName:findResult.nick_name})
      //response.cookie('nick_name',findResult.nick_name,{maxAge:30 * 1000})
      response.cookie('_id',findResult._id.toString(),{maxAge:30 * 1000})
      response.redirect('/usercenter')
    }else{
      errMsg.loginErr = '登錄失敗,郵箱或密碼輸入錯(cuò)誤!'
      //response.send('登錄失敗,郵箱或密碼輸入錯(cuò)誤!')
      response.render('login',{errMsg})
    }
  }
  catch(err){
    console.log(err)
    errMsg.networkErr = '阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!'
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('login',{errMsg})
  }
})
module.exports = router

router/uiRouter.js

/*
* 該模塊是UI路由器模塊,用于管理UI路由,以后配置新頁面,在這里定義路由即可
* */
let {Router} = require('express')
let cookieParser = require('cookie-parser')
//引入用戶模型
let userModel = require('../model/userModel')

let router = new Router()
//引入path模塊,path模塊是node中的核心模塊,無需下載,直接引入即可使用
let {resolve} = require('path')
router.use(cookieParser())


//UI路由--登錄
router.get('/login',(request,response)=>{
  //let filePath = resolve(__dirname,'../public/login.html')
  //response.sendFile(filePath)
  const {email} = request.query
  response.render('login',{errMsg:{email}})
})
//UI路由--注冊
router.get('/register',(request,response)=>{
  //let filePath = resolve(__dirname,'../public/register.html')
  //response.sendFile(filePath)
  response.render('register',{errMsg:{}})
})
//UI路由--個(gè)人中心
router.get('/usercenter',async (request,response)=>{
  const {_id} = request.cookies
  if(_id){
    let result = await userModel.findOne({_id})
    if(result){
      response.render('usercenter',{nickName:result.nick_name})
    }else{
      console.log('用戶非法修改了cookie')
      response.redirect('/login')
    }
  }else{
    response.redirect('/login')
  }

})

module.exports = router

views/login.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登錄頁面</title>
    <style>
        .err{
            color: red;
        }
    </style>
</head>
<body>

<span class="err"><%=errMsg.loginErr%></span>
<span class="err"><%=errMsg.networkErr%></span>
<form action="http://localhost:3000/login" method="post">
  
  郵箱:<input type="email" name="email" value="<%=errMsg.email%>"><span class="err"><%=errMsg.emailErr%></span><br><br>
  密碼:<input type="password" name="password"><span class="err"><%=errMsg.passwordErr%></span><br><br>
  <input type="submit">
  
</form>

</body>
</html>

views/register.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注冊頁面</title>
    <style>
        .err{
            color: red;
        }
    </style>
</head>
<body>
<span class="err"><span class="err"><%=errMsg.networkErr%></span></span>
<form action="http://localhost:3000/register" method="post">
  
  郵&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱:<input type="email" name="email"><span class="err"><%=errMsg.emailErr%></span><br><br>
  昵&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;稱:<input type="text" name="nick_name"><span class="err"><%=errMsg.nickNameErr%></span><br><br>
  密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;碼:<input type="password" name="password"><span class="err"><%=errMsg.passwordErr%></span><br><br>
  確認(rèn)密碼:<input type="password" name="re_password"><span class="err"><%=errMsg.rePasswordErr%></span><br><br>
  
  <input type="submit">
  
</form>

</body>
</html>

view/usercenter.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>個(gè)人中心</title>
</head>
<body>

  <h2><%=nickName%>你好,歡迎訪問您的個(gè)人中心</h2>

</body>
</html>

server.js

//引入express框架
let express = require('express')
//引入數(shù)據(jù)庫連接模塊
let db = require('./db')

//引入U(xiǎn)I路由器
let uiRouter = require('./router/uiRouter')
//引入業(yè)務(wù)路由
let businessRouter = require('./router/businessRouter')

//創(chuàng)建app服務(wù)對象
let app = express()
//配置模板引擎
app.set("view engine" , "ejs");
//配置模板的存放目錄
app.set("views","./views")


//數(shù)據(jù)庫連接成功后,注冊路由
db.then(()=>{
  //使用內(nèi)置中間件用于獲取post請求體參數(shù)
  app.use(express.urlencoded({extended:true}))

  //使用UI路由器中間件
  app.use(uiRouter)
  //使用業(yè)務(wù)路由
  app.use(businessRouter)

}).catch((err)=>{
    console.log('數(shù)據(jù)庫連接失敗',err)
})

//綁定端口監(jiān)聽
app.listen(3000,(err)=>{
    if (!err) console.log('服務(wù)器啟動(dòng)成功了?。?)
    else console.log(err)
})

session

關(guān)于session:
  1.是什么?
      標(biāo)準(zhǔn)來說,session指的是會(huì)話,但是后端人員常說的session,全稱叫:服務(wù)器session會(huì)話存儲(chǔ)。

  2.特點(diǎn):
      1.存在于服務(wù)端
      2.存儲(chǔ)的是瀏覽器和服務(wù)器之間溝通產(chǎn)生的一些信息

  3.默認(rèn)session的存儲(chǔ)在服務(wù)器的內(nèi)存中,每當(dāng)一個(gè)新客戶端發(fā)來請求,服務(wù)器都會(huì)新開辟出一塊空間,供session會(huì)話存儲(chǔ)使用。

  4.工作流程:
      --第一次瀏覽器請求服務(wù)器的時(shí)候,服務(wù)器會(huì)開辟出一塊內(nèi)存空間,供session會(huì)話存儲(chǔ)使用。
      --返回響應(yīng)的時(shí)候,會(huì)自動(dòng)返回一個(gè)cookie(有時(shí)候會(huì)返回多個(gè),為了安全),cookie里包含著,上一步產(chǎn)生會(huì)話存儲(chǔ)“容器”的編號(hào)(id)
      --以后請求的時(shí)候,會(huì)自動(dòng)攜帶這個(gè)cookie,給服務(wù)器。
      --服務(wù)器從該cookie中拿到對應(yīng)的session的id,去服務(wù)器中匹配。
      --服務(wù)器會(huì)根據(jù)匹配信息,決定下一步具體的業(yè)務(wù)邏輯。

  5.備注:1.一般來說cookie一定會(huì)配合session使用。
          2.服務(wù)端一般會(huì)做session的持久化,防止由于服務(wù)器重啟,造成session的丟失。

步驟

1. 下載安裝:npm i express-session --save 用于在express中操作session
2. 下載安裝:npm i connect-mongo --save 用于將session寫入數(shù)據(jù)庫(session持久化)
3. 引入express-session模塊:
  const session = require('express-session')
4. 引入connect-mongo模塊
  const   MongoStore = require('connect-mongo')('session')
5. 編寫全局配置對象:
  app.use(session({
    name: 'userid', //設(shè)置cookie的name,默認(rèn)值是:connect.sid
    secret: 'atguigu', //參與加密的字符串(又稱簽名)
    saveUninitialized: false, //是否存儲(chǔ)內(nèi)容之前創(chuàng)建會(huì)話
    resave: true, //是否在每次請求時(shí),強(qiáng)制重新保存session,即使他們沒有變化
    store: new MongoStore({
      url: 'mongodb://localhost:27017/cookies_container',
      touchAfter: 24 * 3600 //修改頻率(例://在24小時(shí)之內(nèi)只更新一次)
    }),
    cookie: {
      httpOnly: true, //開啟后前端無法通過JS操作cookie
      maxAge: 1000 * 30 //設(shè)置cookie的過期時(shí)間
    }
  }))
6. 向session中添加一個(gè)xxxx,值為yyy: require.session.xxxx = yyy
7. 獲取session上的xxx屬性: const {xxx} = req.session

整個(gè)過程是:
  1.客戶端第一次發(fā)起請求,服務(wù)器開啟了一個(gè)session專門用于存儲(chǔ)這次請求的一些信息。
  2.根據(jù)配置對象的信息,服務(wù)器決定是否進(jìn)行:session持久化等其他操作。
  3.與此同時(shí)服務(wù)器創(chuàng)建一個(gè)cookie,它的key我們可以自己指定,但是它的value一定是上一步session的容器編號(hào)
  4.等請求再次過來時(shí),客戶端的請求中包含著之前“種”的cookie
  5.服務(wù)器檢查攜帶過來的cookie是否有效,決定是否去讀取對應(yīng)session中的信息

登錄注冊(加入session)

db/index.js

/*
* 該模塊用于連接數(shù)據(jù)庫,暴露出去一個(gè)Promise實(shí)例
* 如果連接成功了,Promise實(shí)例內(nèi)部狀態(tài)切換為成功
* 如果連接失敗了,Promise實(shí)例內(nèi)部狀態(tài)切換為失敗
* */
//引入mongoose
let mongoose = require('mongoose')
mongoose.set('useCreateIndex',true)
//定義數(shù)據(jù)庫名
const DB_NAME = 'test'
//定義數(shù)據(jù)庫地址
const DB_URL = 'localhost:27017'
//構(gòu)建一個(gè)Promise實(shí)例,用于管理數(shù)據(jù)庫連接
module.exports = new Promise((resolve,reject)=>{
  //2.連接數(shù)據(jù)庫
  mongoose.connect(`mongodb://${DB_URL}/${DB_NAME}`,{useNewUrlParser:true })

  //3.監(jiān)聽連接狀態(tài)
  mongoose.connection.on('open',(err)=>{
    if(!err){
      console.log(`位于${DB_URL}上的${DB_NAME}數(shù)據(jù)庫連接成功`)
      resolve()
    }else{
      reject(err)
    }
  })
})

model/userModel.js

/*
* 該模塊主要負(fù)責(zé)創(chuàng)建學(xué)生模型
* */
let mongoose = require('mongoose')
//操作數(shù)據(jù)庫
//1.請來一個(gè)保安 ------- 引入約束Schema
let Schema = mongoose.Schema

//2.制定一個(gè)進(jìn)入你家的規(guī)則 -------- 創(chuàng)建一個(gè)約束對象實(shí)例
let userSchema = new Schema({
  email:{
    type:String,
    required:true,
    unique:true
  },
  nick_name:{
    type:String,
    required:true,
  },
  password:{
    type:String,
    required:true,
  },
  date:{
    type:Date,
    default:Date.now()
  },
  enable_flag:{
    type:String,
    default:'Y'
  }
})

/*3.告訴保安你的規(guī)則 ------- 創(chuàng)建模型對象
第一個(gè)參數(shù)與數(shù)據(jù)庫中的集合相對應(yīng),第二個(gè)參數(shù)指定約束對象實(shí)例
只要生成了模型對象,就可以進(jìn)行數(shù)據(jù)的:增刪改查*/
module.exports = mongoose.model('users',userSchema)

router/businessRouter.js

/*
* 該模塊是業(yè)務(wù)路由器,目前管理的業(yè)務(wù)有:登錄、注冊
* */

let {Router} = require('express')

//引入用戶模型
let userModel = require('../model/userModel')

let router = new Router()

//業(yè)務(wù)路由----注冊
router.post('/register',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,nick_name,password,re_password} = request.body
  //2.校驗(yàn)數(shù)據(jù)的合法性
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const nickNameReg = /[\u4e00-\u9fa5]/gm
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  //定義一個(gè)收集錯(cuò)誤信息的對象
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!nickNameReg.test(nick_name)){
    // response.send('昵稱輸入不合法,昵稱應(yīng)為中文')
    // return
    errMsg.nickNameErr = '昵稱輸入不合法,昵稱應(yīng)為中文'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  if(password !== re_password){
    // response.send('兩次輸入密碼不一致')
    // return
    errMsg.rePasswordErr = '兩次輸入密碼不一致'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    //若果進(jìn)入該判斷,意味著用戶輸入的數(shù)據(jù)存在不合法的
    response.render('register',{errMsg})
    return
  }

  //try里面放可能出現(xiàn)錯(cuò)誤的代碼,一旦出現(xiàn)錯(cuò)誤,會(huì)攜帶著錯(cuò)誤信息來到catch中。
  try{
    //3.檢查該郵箱是否注冊過
    let finResult = await userModel.findOne({email})
    if(finResult){
      //response.send(`注冊失敗,${email}郵箱已經(jīng)被注冊了`)
      //return
      errMsg.emailErr = `注冊失敗,${email}郵箱已經(jīng)被注冊了`
      response.render('register',{errMsg})
    }else{
      await userModel.create({email,nick_name,password})
      console.log(`郵箱為:${email},昵稱為:${nick_name}的用戶注冊成功了!`)
      //response.send('注冊成功了!')
      response.redirect(`/login?email=${email}`)
    }
  }
  catch(err){
    //1.計(jì)數(shù) 2.引入警報(bào)模塊
    console.log(err)
    errMsg.networkErr = `阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!`
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('register',{errMsg})
  }
})

//業(yè)務(wù)路由 ---登錄
router.post('/login',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,password} = request.body
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    response.render('login',{errMsg})
    return
  }

  try{
    let findResult = await userModel.findOne({email,password})
    if(findResult){
      //1.在服務(wù)器中開辟一塊內(nèi)存,用于存儲(chǔ)session
      //2.將用戶的id存入上一步產(chǎn)生的session中
      //3.獲取session的編號(hào),放入一個(gè)cookie中
      //4.將上一步的cookie返回給客戶端
      //以上四步可以通過一行代碼搞定
      request.session._id = findResult._id
      response.redirect('/usercenter')
    }else{
      errMsg.loginErr = '登錄失敗,郵箱或密碼輸入錯(cuò)誤!'
      //response.send('登錄失敗,郵箱或密碼輸入錯(cuò)誤!')
      response.render('login',{errMsg})
    }
  }
  catch(err){
    console.log(err)
    errMsg.networkErr = '阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!'
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('login',{errMsg})
  }
})

module.exports = router

router/uiRouter.js

/*
* 該模塊是UI路由器模塊,用于管理UI路由,以后配置新頁面,在這里定義路由即可
* */
let {Router} = require('express')
let cookieParser = require('cookie-parser')
//引入用戶模型
let userModel = require('../model/userModel')

let router = new Router()
//引入path模塊,path模塊是node中的核心模塊,無需下載,直接引入即可使用
let {resolve} = require('path')
router.use(cookieParser())


//UI路由--登錄
router.get('/login',(request,response)=>{
  //let filePath = resolve(__dirname,'../public/login.html')
  //response.sendFile(filePath)
  const {email} = request.query
  response.render('login',{errMsg:{email}})
})
//UI路由--注冊
router.get('/register',(request,response)=>{
  //let filePath = resolve(__dirname,'../public/register.html')
  //response.sendFile(filePath)
  response.render('register',{errMsg:{}})
})
//UI路由--個(gè)人中心
router.get('/usercenter',async (request,response)=>{
  //1.獲取cookie,讀取cookie中session容器編號(hào)
  //2.去服務(wù)器中匹配該編號(hào)對應(yīng)的session容器
  //3.根據(jù)匹配結(jié)果,進(jìn)行具體的業(yè)務(wù)邏輯
  const {_id} = request.session
  if(_id){
    let result = await userModel.findOne({_id})
    if(result){
      response.render('usercenter',{nickName:result.nick_name})
    }else{
      console.log('用戶非法修改了cookie')
      response.redirect('/login')
    }
  }else{
    response.redirect('/login')
  }

})

module.exports = router

views/login.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>登錄頁面</title>
    <style>
        .err{
            color: red;
        }
    </style>
</head>
<body>

<span class="err"><%=errMsg.loginErr%></span>
<span class="err"><%=errMsg.networkErr%></span>
<form action="http://localhost:3000/login" method="post">
  
  郵箱:<input type="email" name="email" value="<%=errMsg.email%>"><span class="err"><%=errMsg.emailErr%></span><br><br>
  密碼:<input type="password" name="password"><span class="err"><%=errMsg.passwordErr%></span><br><br>
  <input type="submit">
  
</form>

</body>
</html>

views/register.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>注冊頁面</title>
    <style>
        .err{
            color: red;
        }
    </style>
</head>
<body>
<span class="err"><span class="err"><%=errMsg.networkErr%></span></span>
<form action="http://localhost:3000/register" method="post">
  
  郵&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱:<input type="email" name="email"><span class="err"><%=errMsg.emailErr%></span><br><br>
  昵&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;稱:<input type="text" name="nick_name"><span class="err"><%=errMsg.nickNameErr%></span><br><br>
  密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;碼:<input type="password" name="password"><span class="err"><%=errMsg.passwordErr%></span><br><br>
  確認(rèn)密碼:<input type="password" name="re_password"><span class="err"><%=errMsg.rePasswordErr%></span><br><br>
  
  <input type="submit">
  
</form>

</body>
</html>

views/usercenter.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>個(gè)人中心</title>
</head>
<body>

<h2><%=nickName%>你好,歡迎訪問您的個(gè)人中心</h2>

</body>
</html>

server.js

//引入express框架
let express = require('express')
//引入數(shù)據(jù)庫連接模塊
let db = require('./db')

//引入U(xiǎn)I路由器
let uiRouter = require('./router/uiRouter')
//引入業(yè)務(wù)路由
let businessRouter = require('./router/businessRouter')
//引入express-session用于在express中操作session
let session = require('express-session');
//引入connect-mongo用于session持久化
const MongoStore = require('connect-mongo')(session);

//創(chuàng)建app服務(wù)對象
let app = express()
//配置模板引擎
app.set("view engine" , "ejs");
//配置模板的存放目錄
app.set("views","./views")
//定義一個(gè)cookie和session組合使用的配置對象
app.use(session({
  name: 'haha',   //設(shè)置cookie的name,默認(rèn)值是:connect.sid
  secret: 'atguigu', //參與加密的字符串(又稱簽名)
  saveUninitialized: false, //是否在存儲(chǔ)內(nèi)容之前創(chuàng)建會(huì)話
  resave: true ,//是否在每次請求時(shí),強(qiáng)制重新保存session,即使他們沒有變化
  store: new MongoStore({
    url: 'mongodb://localhost:27017/cookies_container',
    touchAfter: 1800//修改頻率(例://在24小時(shí)之內(nèi)只更新一次)
  }),
  cookie: {
    httpOnly: true, // 開啟后前端無法通過 JS 操作cookie
    maxAge: 1000*30 // 設(shè)置cookie的過期時(shí)間
  },
}));


//數(shù)據(jù)庫連接成功后,注冊路由
db.then(()=>{
  //使用內(nèi)置中間件用于獲取post請求體參數(shù)
  app.use(express.urlencoded({extended:true}))

  //使用UI路由器中間件
  app.use(uiRouter)
  //使用業(yè)務(wù)路由
  app.use(businessRouter)

}).catch((err)=>{
    console.log('數(shù)據(jù)庫連接失敗',err)
})

//綁定端口監(jiān)聽
app.listen(3000,(err)=>{
    if (!err) console.log('服務(wù)器啟動(dòng)成功了??!')
    else console.log(err)
})

sha1加密和md5加密

/*
* 該模塊是業(yè)務(wù)路由器,目前管理的業(yè)務(wù)有:登錄、注冊
* */

let {Router} = require('express')

//引入用戶模型
let userModel = require('../model/userModel')
//引入sha1加密
let sha1 = require('sha1')

let router = new Router()

//業(yè)務(wù)路由----注冊
router.post('/register',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,nick_name,password,re_password} = request.body
  //2.校驗(yàn)數(shù)據(jù)的合法性
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const nickNameReg = /[\u4e00-\u9fa5]/gm
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  //定義一個(gè)收集錯(cuò)誤信息的對象
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!nickNameReg.test(nick_name)){
    // response.send('昵稱輸入不合法,昵稱應(yīng)為中文')
    // return
    errMsg.nickNameErr = '昵稱輸入不合法,昵稱應(yīng)為中文'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  if(password !== re_password){
    // response.send('兩次輸入密碼不一致')
    // return
    errMsg.rePasswordErr = '兩次輸入密碼不一致'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    //若果進(jìn)入該判斷,意味著用戶輸入的數(shù)據(jù)存在不合法的
    response.render('register',{errMsg})
    return
  }

  //try里面放可能出現(xiàn)錯(cuò)誤的代碼,一旦出現(xiàn)錯(cuò)誤,會(huì)攜帶著錯(cuò)誤信息來到catch中。
  try{
    //3.檢查該郵箱是否注冊過
    let finResult = await userModel.findOne({email})
    if(finResult){
      //response.send(`注冊失敗,${email}郵箱已經(jīng)被注冊了`)
      //return
      errMsg.emailErr = `注冊失敗,${email}郵箱已經(jīng)被注冊了`
      response.render('register',{errMsg})
    }else{
      await userModel.create({email,nick_name,password:sha1(password)})
      console.log(`郵箱為:${email},昵稱為:${nick_name}的用戶注冊成功了!`)
      //response.send('注冊成功了!')
      response.redirect(`/login?email=${email}`)
    }
  }
  catch(err){
    //1.計(jì)數(shù) 2.引入警報(bào)模塊
    console.log(err)
    errMsg.networkErr = `阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!`
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('register',{errMsg})
  }
})

//業(yè)務(wù)路由 ---登錄
router.post('/login',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,password} = request.body
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    response.render('login',{errMsg})
    return
  }

  try{
    let findResult = await userModel.findOne({email,password:sha1(password)})
    if(findResult){
      //1.在服務(wù)器中開辟一塊內(nèi)存,用于存儲(chǔ)session
      //2.將用戶的id存入上一步產(chǎn)生的session中
      //3.獲取session的編號(hào),放入一個(gè)cookie中
      //4.將上一步的cookie返回給客戶端
      //以上四步可以通過一行代碼搞定
      request.session._id = findResult._id
      response.redirect('/usercenter')
    }else{
      errMsg.loginErr = '登錄失敗,郵箱或密碼輸入錯(cuò)誤!'
      //response.send('登錄失敗,郵箱或密碼輸入錯(cuò)誤!')
      response.render('login',{errMsg})
    }
  }
  catch(err){
    console.log(err)
    errMsg.networkErr = '阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!'
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('login',{errMsg})
  }
})
module.exports = router
/*
* 該模塊是業(yè)務(wù)路由器,目前管理的業(yè)務(wù)有:登錄、注冊
* */

let {Router} = require('express')

//引入用戶模型
let userModel = require('../model/userModel')
//引入sha1加密
let md5 = require('md5')

let router = new Router()

//業(yè)務(wù)路由----注冊
router.post('/register',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,nick_name,password,re_password} = request.body
  //2.校驗(yàn)數(shù)據(jù)的合法性
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const nickNameReg = /[\u4e00-\u9fa5]/gm
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  //定義一個(gè)收集錯(cuò)誤信息的對象
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!nickNameReg.test(nick_name)){
    // response.send('昵稱輸入不合法,昵稱應(yīng)為中文')
    // return
    errMsg.nickNameErr = '昵稱輸入不合法,昵稱應(yīng)為中文'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  if(password !== re_password){
    // response.send('兩次輸入密碼不一致')
    // return
    errMsg.rePasswordErr = '兩次輸入密碼不一致'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    //若果進(jìn)入該判斷,意味著用戶輸入的數(shù)據(jù)存在不合法的
    response.render('register',{errMsg})
    return
  }

  //try里面放可能出現(xiàn)錯(cuò)誤的代碼,一旦出現(xiàn)錯(cuò)誤,會(huì)攜帶著錯(cuò)誤信息來到catch中。
  try{
    //3.檢查該郵箱是否注冊過
    let finResult = await userModel.findOne({email})
    if(finResult){
      //response.send(`注冊失敗,${email}郵箱已經(jīng)被注冊了`)
      //return
      errMsg.emailErr = `注冊失敗,${email}郵箱已經(jīng)被注冊了`
      response.render('register',{errMsg})
    }else{
      await userModel.create({email,nick_name,password:md5(password)})
      console.log(`郵箱為:${email},昵稱為:${nick_name}的用戶注冊成功了!`)
      //response.send('注冊成功了!')
      response.redirect(`/login?email=${email}`)
    }
  }
  catch(err){
    //1.計(jì)數(shù) 2.引入警報(bào)模塊
    console.log(err)
    errMsg.networkErr = `阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!`
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('register',{errMsg})
  }
})

//業(yè)務(wù)路由 ---登錄
router.post('/login',async(request,response)=>{
  //1.獲取用戶的輸入
  const {email,password} = request.body
  //定義正則表達(dá)式
  const emailReg = /^[a-zA-Z0-9_]{2,16}@[a-zA-Z0-9]{2,16}\.com$/
  const passwordReg = /^[a-zA-Z0-9_#]{6,16}$/
  const errMsg = {}
  //使用正則進(jìn)行校驗(yàn)
  if(!emailReg.test(email)){
    //response.send('郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位')
    //return
    errMsg.emailErr = '郵箱輸入不合法!要求郵箱用戶名2-16位不包含特殊字符,郵箱主機(jī)名2-16位'
  }
  if(!passwordReg.test(password)){
    // response.send('密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符')
    // return
    errMsg.passwordErr = '密碼輸入不合法,密碼應(yīng)為6-16位字符不包含特殊字符'
  }
  //判斷錯(cuò)誤對象是否為空
  if(JSON.stringify(errMsg) !== '{}'){
    response.render('login',{errMsg})
    return
  }

  try{
    let findResult = await userModel.findOne({email,password:md5(password)})
    if(findResult){
      //1.在服務(wù)器中開辟一塊內(nèi)存,用于存儲(chǔ)session
      //2.將用戶的id存入上一步產(chǎn)生的session中
      //3.獲取session的編號(hào),放入一個(gè)cookie中
      //4.將上一步的cookie返回給客戶端
      //以上四步可以通過一行代碼搞定
      request.session._id = findResult._id
      response.redirect('/usercenter')
    }else{
      errMsg.loginErr = '登錄失敗,郵箱或密碼輸入錯(cuò)誤!'
      //response.send('登錄失敗,郵箱或密碼輸入錯(cuò)誤!')
      response.render('login',{errMsg})
    }
  }
  catch(err){
    console.log(err)
    errMsg.networkErr = '阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!'
    //response.send('阿偶,網(wǎng)絡(luò)不穩(wěn)定,稍后重試!')
    response.render('login',{errMsg})

  }
})

module.exports = router
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容