Node.js_express_瀏覽器存儲技術 Cookie(服務器將少許數據交於瀏覽器存儲管理)

瀏覽器存儲技術 Cookiecss

服務器將少許數據交於瀏覽器存儲管理html

解決 http 無狀態協議的問題(沒法區分屢次請求是否發送自同一客戶端前端

一個網頁通常最多 20個的 cookie,每一個 cookie 通常 4KBnode

第一次訪問 url,服務器會建立一個 Cookie 給瀏覽器mongodb

瀏覽器會保存 Cookie,之後每次請求,都會攜帶全部 Cookie,一併發送給服務器數據庫

  • 登陸 Cookie

1. 瀏覽器發送請求給服務器,請求登陸express

  • app.get('/cookie1', (request, response)=>{ response.cookie('userid', '123456', {masAge: 100*3600*24}); response.send('cookie1 的 get 請求 的響應'); });

2. 服務器返回響應給瀏覽器,會建立併發送 Cookie(包含了當前用戶的惟一標識)npm

3. 瀏覽器接受響應,會將 Cookie 保存下來json

4. 瀏覽器下一次發送請求時,都會自動攜帶上 Cookiepromise

  • npm install cookie-parser
  • const cookieParser = require('cookie-parser');
    app.use(cookieParser()); // 應用中間件,解析 Cookie 的數據,掛載到 request.cookie 上
    app.get('/cookie2', (request, response)=>{ response.send(request.cookies); });

5. 服務器接受到請求,解析 Cookie,從而判斷是哪一個用戶發送的請求(解決 http 協議無狀態問題)

6.  主動清除 Cookie

  • app.get('/cookie3', (request, response)=>{ response.clearCookie('userid'); response.send('key 爲 userid 的 cookie 已經清除'); });
  • 前端操做 Cookie
  • 清除 Cookie
  • document.cookie = 'hello=123; expires=' + new Date(Data.now()-1000);
  • 判斷用戶到底登陸沒?哪一個用戶登陸的?

不能將用戶的隱私直接暴露

數據加密 或者 數據庫文檔 id 裝進 Cookie

res.cookie('userid', user.id, {maxAge: 1000*24*3600*7});

  • const cookieParser = require('cookie-parser'); indexRouter.use(cookieParser()); // 應用中間件,解析 Cookie 的數據,掛載到 request.cookie 上
     indexRouter.get('/user_center',async (request, response)=>{  const {userId} = request.cookies; if(userId){    // 用戶已經登陸
                    const findRet = await userInfoModel.findOne({"_id":userId}); if(findRet){ let serverInfo = {uName:findRet.userName}; response.render('user_center.ejs', {serverInfo}); }else{    // 惡意 Cookie
                            response.clearCookie("userId"); response.redirect('/login'); }; }else{    // 用戶未登陸
                    response.redirect('/login'); }; });
  • 登陸註冊實例

package.json

  • { "name": "node_express", "version": "1.0.0", "main": "index.js", "license": "MIT", "dependencies": { "connect-mongo": "^2.0.3", "cookie-parser": "^1.4.3", "ejs": "^2.6.1", "express": "^4.16.4", "mongoose": "^5.4.0", "sha1": "^1.1.1" } }

public/register.html

  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>用戶註冊</title>
            
            <link rel="stylesheet" type="text/css" href="css/index.css"/>
        </head>
        
        <body>
            <div id="outer_box" class="register">
                <h2>用戶註冊</h2>
                <form action="http://localhost:3000/register" method="post">
                    <div class="clothes">
                        <label for="input_name">用&nbsp;戶&nbsp;名</label>
                        <input id="input_name" type="text" name="user_name" placeholder="請輸入用戶名" />
                    </div>
            
                    <div class="clothes">
                        <label for="input_pwd">密&nbsp;&nbsp;&nbsp;碼</label>
                        <input id="input_pwd" type="password" name="user_pwd" placeholder="請輸入密碼" />
                    </div>
                    
                    <div class="clothes">
                        <label for="input_repeat_pwd">確認密碼</label>
                        <input id="input_repeat_pwd" type="password" name="user_repeat_pwd" placeholder="請再次輸入密碼" />
                    </div>
                    
                    <div class="clothes">
                        <label for="input_email">註冊郵箱</label>
                        <input id="input_email" type="text" name="user_email" placeholder="請輸入郵箱地址" />
                    </div>
                    
                    <div class="clothes">
                        <button class="register btn" type="submit">註冊</button>
                        <a class="btn" href="http://localhost:3000/login">
                            <button type="button">登陸</button>
                        </a>
                    </div>
                </form>
            </div>
        </body>
    </html>

public/login.html

  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>用戶登陸</title>
            
            <link rel="stylesheet" type="text/css" href="css/index.css"/>
        </head>
        
        <body>
            <div id="outer_box" class="login">
                <h2>用戶登陸</h2>
                <form action="http://localhost:3000/login" method="post">
                    <div class="clothes">
                        <label for="input_name">用&nbsp;戶&nbsp;名</label>
                        <input id="input_name" type="text" name="user_name" placeholder="請輸入用戶名" />
                    </div>
                    
                    <div class="clothes">
                        <label for="input_pwd">密&nbsp;&nbsp;&nbsp;碼</label>
                        <input id="input_pwd" type="password" name="user_pwd" placeholder="請輸入密碼" />
                    </div>
                    
                    <div class="clothes">
                        <a class="btn" href="http://localhost:3000/register">
                            <button type="button">註冊</button>
                        </a>
                        <button class="login btn" type="submit">登陸</button>
                    </div>
                </form>
            </div>
        </body>
    </html>

public/user_center.html

  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>用戶中心</title>
            
            <link rel="stylesheet" type="text/css" href="css/index.css"/>
        </head>
        
        <body>
            <div id="outer_box" class="login">
                <h2>我的空間</h2>
            </div>
        </body>
    </html>

public/css/index.css

  • body { width: 100%; height: 100%; color: #000; background: #b9c2a4; background-size: cover; /* 指定背景圖片大小 */ } /*************************************************/ #outer_box { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #1a45c3; } #outer_box.login { color: #9e098b; } #outer_box.register { color: #1a45c3; } #outer_box>h2{ padding-bottom: 40px; margin-left: -50px; } .clothes { position: relative; width: 260px; display: flex; justify-content: space-between; margin: 20px 0; font-size: 18px; line-height: 32px; } .tips { position: absolute; top: 0; right: -100%; margin-left: -50%; margin-top: 2px; width: 252px; height: 32px; text-align: center; color: #f00; } .clothes>label{ width: 80px; text-align: center; } .clothes>input{ width: 170px; height: 32px; } button { width: 100%; height: 100%; font-size: 16px; background-color: #c4ceda; cursor: pointer; } .clothes .btn{ width: 64px; height: 32px; margin: 0 20px; } .clothes button.register{ background-color: #1a45c3; color: #fff; } .clothes button.login{ background-color: #9e098b; color: #fff; } #outer_box>h2 { position: relative; } #server_info { display: block; width: 139px; height: 20px; border-radius: 10px; position: absolute; top: 0; right: 0; color: red; font-size: 14px; text-align: center; line-height: 20px; background-color: #cecece; }

views/register.ejs

  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>用戶註冊</title>
            
            <link rel="stylesheet" type="text/css" href="css/index.css"/>
        </head>
        
        <body>
            <div id="outer_box" class="register">
                <h2>用戶註冊</h2>
                <form action="http://localhost:3000/register" method="post">
                    <div class="clothes">
                        <label for="input_name">用&nbsp;戶&nbsp;名</label>
                        <input id="input_name" type="text" name="user_name" value="<%= serverInfo.uName %>" placeholder="請輸入用戶名" />
                        <div class="tips"><%= serverInfo.nameErr %></div>
                    </div>
            
                    <div class="clothes">
                        <label for="input_pwd">密&nbsp;&nbsp;&nbsp;碼</label>
                        <input id="input_pwd" type="password" name="user_pwd" placeholder="請輸入密碼" />
                        <div class="tips"><%= serverInfo.passwordErr %></div>
                    </div>
                    
                    <div class="clothes">
                        <label for="input_repeat_pwd">確認密碼</label>
                        <input id="input_repeat_pwd" type="password" name="user_repeat_pwd" placeholder="請再次輸入密碼" />
                        <div class="tips"><%= serverInfo.repeatErr %></div>
                    </div>
                    
                    <div class="clothes">
                        <label for="input_email">註冊郵箱</label>
                        <input id="input_email" type="text" name="user_email" value="<%= serverInfo.uEmail %>" placeholder="請輸入郵箱地址" />
                        <div class="tips"><%= serverInfo.emailErr %></div>
                    </div>
                    
                    <div class="clothes">
                        <button class="register btn" type="submit">註冊</button>
                        <a class="btn" href="http://localhost:3000/login">
                            <button type="button">登陸</button>
                        </a>
                    </div>
                </form>
            </div>
        </body>
    </html>

views/login.ejs

  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>用戶登陸</title>
            
            <link rel="stylesheet" type="text/css" href="css/index.css"/>
        </head>
        
        <body>
            <div id="outer_box" class="login">
                <h2> 用戶登陸 <div id="server_info">
                        <%= serverInfo.tips %>
                    </div>
                </h2>
                <form action="http://localhost:3000/login" method="post">
                    <div class="clothes">
                        <label for="input_name">用&nbsp;戶&nbsp;名</label>
                        <input id="input_name" type="text" name="user_name" value="<%= serverInfo.uName %>" placeholder="請輸入用戶名" />
                    </div>
                    
                    <div class="clothes">
                        <label for="input_pwd">密&nbsp;&nbsp;&nbsp;碼</label>
                        <input id="input_pwd" type="password" name="user_pwd" placeholder="請輸入密碼" />
                    </div>
                    
                    <div class="clothes">
                        <a class="btn" href="http://localhost:3000/register">
                            <button type="button">註冊</button>
                        </a>
                        <button class="login btn" type="submit">登陸</button>
                    </div>
                </form>
            </div>
        </body>
    </html>

views/user_center.ejs

  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>用戶中心</title>
            
            <link rel="stylesheet" type="text/css" href="css/index.css"/>
        </head>
        
        <body>
            <div id="outer_box" class="login">
                <h2><%= serverInfo.uName%> - 我的空間</h2>
            </div>
        </body>
    </html>

db/connectDB.js

  • const mongoose = require('mongoose'); module.exports = new Promise((resolve, reject)=>{ mongoose.connect('mongodb://localhost:27017/user_database', {useNewUrlParser:true}) mongoose.connection.once('open', err=>{ if(err){ console.log(err); reject(err); }else{ resolve('數據庫已鏈接'); }; }); });

models/userModel.js

  • const mongoose = require('mongoose'); const Schema = mongoose.Schema; const fieldSchema = new Schema({ "userName": { "type": String, "unique": true, "required": true }, "userPassword": { "type": String, "required": true }, "userEmail": { "type": String, "unique": true, "required": true }, "createTime": { "type": Date, "default": Date.now() } }); module.exports = mongoose.model("user_info", fieldSchema);

routers/get/index_router.js

  • const express = require('express'); const promiseConnect = require('../../db/connectDB.js'); const userInfoModel = require('../../models/userModel.js'); const {resolve} = require('path'); const cookieParser = require('cookie-parser'); const indexRouter = new express.Router(); indexRouter.use(cookieParser()); /************************ get ***********************/ indexRouter.get('/', (request, response)=>{ response.sendFile(resolve(__dirname, '../../public/login.html')); }); indexRouter.get('/login', (request, response)=>{ response.sendFile(resolve(__dirname, '../../public/login.html')); }); indexRouter.get('/register', (request, response)=>{ response.sendFile(resolve(__dirname, '../../public/register.html')); }); promiseConnect.then(result=>{ console.log("index_router.js - "+result); indexRouter.get('/user_center',async (request, response)=>{ const {userId} = request.cookies; if(userId){    // 用戶已經登陸
                            const findRet = await userInfoModel.findOne({"_id":userId}); if(findRet){ let serverInfo = {uName:findRet.userName}; response.render('user_center.ejs', {serverInfo}); }else{    // 惡意 Cookie
                                    response.clearCookie("userId"); response.redirect('/login'); }; }else{    // 用戶未登陸
                             response.redirect('/login'); }; }); }).catch(err=>console.log(err)); module.exports = indexRouter;

routers/post/form_router.js

  • const express =  require('express'); const sha1 =  require('sha1'); const promiseConnect = require('../../db/connectDB.js'); const userInfoModel = require('../../models/userModel.js'); const formRouter = new express.Router(); /************************ post ***********************/ let logged = false ; promiseConnect.then(result=>{ console.log("form_router.js - "+result); formRouter.post('/register', async (request, response)=>{ const { user_name:uName, user_pwd:uPwd, user_repeat_pwd:urePwd, user_email:uEmail, } = request.body;    /**** 解構賦值 ****/ userInfo = { "userName": uName, "userPassword": uPwd, "userEmail": uEmail }; let serverInfo = {uName, uEmail}; if(urePwd !== uPwd){ serverInfo.repeatErr = '密碼兩次輸入不一致'; }; if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){ serverInfo.nameErr = '用戶名不合法'; }; if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){ serverInfo.passwordErr = '密碼不合法'; }; if(!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(uEmail))){ serverInfo.emailErr = '郵箱不合法'; }; const fond = await userInfoModel.findOne({"userName": uName}); if(fond){ serverInfo.nameErr = '用戶名已被註冊'; }; const badEmail = await userInfoModel.findOne({"userEmail": uEmail}); if(badEmail){ serverInfo.emailErr = '郵箱已被註冊'; }; if(serverInfo.repeatErr || serverInfo.nameErr || serverInfo.passwordErr || serverInfo.emailErr){ response.render('register.ejs', {serverInfo});    // 渲染錯誤信息
                            return; }else{ userInfo.userPassword = sha1(userInfo.userPassword); await userInfoModel.create(userInfo); response.redirect('/login');    // 跳轉到登陸
     }; }); formRouter.post('/login',async (request, response)=>{ logged = false; let uName = request.body['user_name']; let uPwd = request.body['user_pwd']; userInfo = { "userName": uName, "userPassword": uPwd }; if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){ logged = false; }else if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){ logged = false; }; try{ const findName = await userInfoModel.findOne({"userName": uName}); if(findName && (findName.userPassword===sha1(uPwd)) ){ logged = true; }; let serverInfo = {uName}; if(logged){ response.cookie('userId', findName.id, {maxAge: 1000*24*3600*7}); response.redirect('/user_center');    // 跳轉到用戶 我的空間 頁面
                            }else{ serverInfo.tips='用戶名或密碼錯誤'; response.render('login.ejs', {serverInfo});    // 渲染錯誤信息
     }; }catch(err) { cosole.log(err); } }); }).catch(err=>console.log(err)); module.exports = formRouter;

index.js

  • const express =  require('express'); const app = express(); const indexRouter = require('./routers/get/index_router.js'); const formRouter = require('./routers/post/form_router.js'); app.set('views', 'views');    // 1. 配置模板路徑
    app.set('view engine', 'ejs');    // 2. 配置模板引擎
    
    /*********************** 中間件 **********************/
    // 暴露路由 login.html register.html
    app.use(express.static('public'));    // 默認調用 next();
    
    // 將 用戶輸入的數據 掛載到 請求體 request.body 上
    app.use(express.urlencoded({extended: true}));    // 默認調用 next();
     app.use(indexRouter); app.use(formRouter); /**************** 端口號 3000, 啓動服務器 ***************/ app.listen(3000, err=>console.log(err?err:'\n\n服務器已啓動: http://localhost:3000\n\t\tHunting Happy!'));
相關文章
相關標籤/搜索