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