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中。

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