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">
郵 箱:<input type="email" name="email"><span class="err"><%=errMsg.emailErr%></span><br><br>
昵 稱:<input type="text" name="nick_name"><span class="err"><%=errMsg.nickNameErr%></span><br><br>
密 碼:<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">
郵 箱:<input type="email" name="email"><span class="err"><%=errMsg.emailErr%></span><br><br>
昵 稱:<input type="text" name="nick_name"><span class="err"><%=errMsg.nickNameErr%></span><br><br>
密 碼:<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