Vue+element+Nodejs學習記錄(4)

1.nodejs中使用redis

const redis = require('redis')

// 創建客戶端
const redisClient = redis.createClient(6379, '127.0.0.1')
redisClient.on('error', err => {
    console.error(err)
})

// 測試
redisClient.set('myname', 'zhangsan2', redis.print)
redisClient.get('myname', (err, val) => {
    if (err) {
        console.error(err)
        return
    }
    console.log('val ', val)

    // 退出
    redisClient.quit()
})

2.Nodejs中封裝redis以及整體使用

conf/db.js

const env = process.env.NODE_ENV  // 環境參數

// 配置
let MYSQL_CONF
let REDIS_CONF

if (env === 'dev') {
    // mysql
    MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: 'Mysql_2018',
        port: '3306',
        database: 'myblog'
    }

    // redis
    REDIS_CONF = {
        port: 6379,
        host: '127.0.0.1'
    }
}

db/redis.js

const redis = require('redis')
const { REDIS_CONF } = require('../conf/db.js')

// 創建客戶端
const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host)
redisClient.on('error', err => {
    console.error(err)
})

function set(key, val) {
    if (typeof val === 'object') {
        val = JSON.stringify(val)
    }
    redisClient.set(key, val, redis.print)
}

function get(key) {
    const promise = new Promise((resolve, reject) => {
        redisClient.get(key, (err, val) => {
            if (err) {
                reject(err)
                return
            }
            if (val == null) {
                resolve(null)
                return
            }

            try {
                resolve(
                    JSON.parse(val)
                )
            } catch (ex) {
                resolve(val)
            }
        })
    })
    return promise
}

module.exports = {
    set,
    get
}

app.js

const { get, set } = require('./src/db/redis')

// 解析 session (使用 redis)
let needSetCookie = false
let userId = req.cookie.userid
if (!userId) {
    needSetCookie = true
    userId = `${Date.now()}_${Math.random()}`
    // 初始化 redis 中的 session 值
    set(userId, {})
}
// 獲取 session
req.sessionId = userId
get(req.sessionId).then(sessionData => {
    if (sessionData == null) {
        // 初始化 redis 中的 session 值
        set(req.sessionId, {})
        // 設置 session
        req.session = {}
    } else {
        // 設置 session
        req.session = sessionData
    }
    // console.log('req.session ', req.session)

    // 處理 post data
    return getPostData(req)
})
.then(postData => {
    req.body = postData

    // 處理 blog 路由
    // const blogData = handleBlogRouter(req, res)
    // if (blogData) {
    //     res.end(
    //         JSON.stringify(blogData)
    //     )
    //     return
    // }
    const blogResult = handleBlogRouter(req, res)
    if (blogResult) {
        blogResult.then(blogData => {
            if (needSetCookie) {
                res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
            }

            res.end(
                JSON.stringify(blogData)
            )
        })
        return
    }
    
    // 處理 user 路由
    // const userData = handleUserRouter(req, res)
    // if (userData) {
    //     res.end(
    //         JSON.stringify(userData)
    //     )
    //     return
    // }
    const userResult = handleUserRouter(req, res)
    if (userResult) {
        userResult.then(userData => {
            if (needSetCookie) {
                res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
            }

            res.end(
                JSON.stringify(userData)
            )
        })
        return
    }

    // 未命中路由,返回 404
    res.writeHead(404, {"Content-type": "text/plain"})
    res.write("404 Not Found\n")
    res.end()
})

router/user.js

const { login } = require('../controller/user')
const { SuccessModel, ErrorModel } = require('../model/resModel')
const { set } = require('../db/redis')

const handleUserRouter = (req, res) => {
    const method = req.method // GET POST

    // 登錄
    if (method === 'POST' && req.path === '/api/user/login') {
        const { username, password } = req.body
        // const { username, password } = req.query
        const result = login(username, password)
        return result.then(data => {
            if (data.username) {
                // 設置 session
                req.session.username = data.username
                req.session.realname = data.realname
                // 同步到 redis
                set(req.sessionId, req.session)

                return new SuccessModel()
            }
            return new ErrorModel('登錄失敗')
        })
    }

    // 登錄驗證的測試
    if (method === 'GET' && req.path === '/api/user/login-test') {
        if (req.session.username) {
            return Promise.resolve(
                new SuccessModel({
                    session: req.session
                })
            )
        }
        return Promise.resolve(
            new ErrorModel('尚未登錄')
        )
    }
}

module.exports = handleUserRouter

3.正向代理和反向代理

nginx介紹:
1.高性能的web服務器,開源免費
2.一般用於做靜態服務、負載均衡(本課用不到)
3.還有反向代理(本課用到)

正向代理:
前向代理作爲客戶端的代理,將從互聯網上獲取的資源返回給一個或多個的客戶端,服務端(如Web服務器)只知道代理的IP地址而不知道客戶端的IP地址;

所謂反向代理:
服務器根據客戶端的請求,從其關聯的一組或多組後端服務器(如Web服務器)上獲取資源,然後再將這些資源返回給客戶端,客戶端只會得知反向代理的IP地址,而不知道在代理服務器後面的服務器簇的存在。

在這裏插入圖片描述
訪問localhost/index.html是8080端口,經過nginx反向代理,遇見/…形式代理到8081端口,遇見/api/…代理到nodejs後端服務器。瀏覽器只知道代理的IP地址,不知道後端html靜態文件和nodejs後端服務器的存在。

Nginx系列文章:https://blog.csdn.net/Milogenius/column/info/20827

1.	啓動
start nginx / nginx.exe

2.	停止
nginx -s stop 快速停止nginx,可能並不保存相關信息
nginx -s quit 完整有序的停止nginx,並保存相關信息

3.	重啓
nginx -s reload 優雅重啓,並重新載入配置文件nginx.conf

4.	nginx -s reopen
重新打開日誌文件,一般用於切割日誌

5.	nginx -v 查看版本

6.nginx -t 檢查nginx的配置文件

7.nginx -V 詳細版本信息,包括編譯參數

8.nginx -c filename 指定配置文件

主要配置:

server {
  listen 80;   //nginx默認80端口
  server_name 你的域名;
  location / {
    proxy_pass 本地ip+端口號;
  }
}

//一個實例
http{

	server{
		listen	8800;
		server_name	localhost;

		location	/	{
			proxy_pass http://localhost:8000;
		}

		location /api/ {	
			proxy_pass http://localhost:8000;
			proxy_set_header Host $host;
		}
		
	}

}

proxy_pass可以參考:https://blog.csdn.net/ainuser/article/details/80260144
proxy_set_header可以參考:
https://blog.csdn.net/felix_yujing/article/details/51682655
https://www.cnblogs.com/jsonhc/p/7199295.html?utm_source=itdadao&utm_medium=referral#top

前端聯調界面

cnpm install http-server -g
http-server -p 8001

然後就可以輸入localhost:8001/xxx.html進行訪問了

url拼接參數格式

可以參考:https://www.cnblogs.com/yanggb/p/11143489.html

4.用戶名密碼加密

utils/cryp.js

const crypto = require('crypto')

// 密匙
const SECRET_KEY = 'WJiol_8776#'

// md5 加密
function md5(content) {
    let md5 = crypto.createHash('md5')
    return md5.update(content).digest('hex')
}

// 加密函數
function genPassword(password) {
    const str = `password=${password}&key=${SECRET_KEY}`
    return md5(str)
}

module.exports = {
    genPassword
}

5.原生Node博客知識點總結

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

server和前端的區別:

在這裏插入圖片描述

6.Express初始化環境

關於登陸:
1.使用express-session和connect-redis管理,簡單方便
2.req.session保存登錄信息,
3.登陸校驗loginCheck做成express中間件 ,因爲一些操作要驗證是否已經登陸

關於Express中使用cookie、session和redis參考文章:
https://segmentfault.com/a/1190000013048314#articleHeader0
https://andrewpqc.github.io/2017/09/17/cookie-and-session-in-Express-use-redis-to-make-it-work-better/
http://kirochen.com/2015/07/09/about-cookie-session/
https://techblog.toutiao.com/2017/11/29/nodezhong-sessionchi-jiu-hua-yu-redishuan-cun/
https://juejin.im/post/5a27a867f265da432652b618

現在來看具體代碼:

//app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

const session = require('express-session')
const RedisStore = require('connect-redis')(session)

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

const blogRouter = require('./routes/blog');
const userRouter = require('./routes/user')


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')));

const redisClient = require('./db/redis')
const sessionStore = new RedisStore({
  client: redisClient
})
app.use(session({
  secret: 'WJiol#23123_',
  cookie: {
    // path: '/',   // 默認配置,不寫也可以
    // httpOnly: true,  // 默認配置
    maxAge: 24 * 60 * 60 * 1000
  },
  store: sessionStore
}))


app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/api/blog', blogRouter);
app.use('/api/user', userRouter);

// 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;

//routes/user.js
router.post('/login', function(req, res, next) {
    const { username, password } = req.body
    const result = login(username, password)
    return result.then(data => {
        if (data.username) {
            // 設置 session
            req.session.username = data.username
            req.session.realname = data.realname

            res.json(
                new SuccessModel()
            )
            return
        }
        res.json(
            new ErrorModel('登錄失敗')
        )
    })
});

app.js中app.use(session)中間件作用可以理解爲註冊session和開闢redis空間,如果不是登陸路由,其他路由依然會創建session對象和cookie值,並在session值存儲到redis中,但登陸路由執行後,對session賦值,並存儲到redis中。
在這裏插入圖片描述
所以請求(不論是不是登陸)服務端都會生成session和cookie,並保存到redis中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章