03——博客项目之登陆04

1.nodejs 连接 redis 的 Demo
2.nodejs 连接 redis–封装成工具
3.redis 使用
4.server端登陆

1.nodejs 连接 redis 的 Demo

目录:
node-redis

way liu@DESKTOP-NG9KB5L MINGW64 /e/work-vscode/node-redis
$ npm i redis --save

index.js

const redis = require('redis')

// 创建客户端
const redisClient = redis.createClient(6379, '127.0.0.1',{auth_pass:123456})
redisClient.on('error', err => {
    console.log(err)
})

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

    // 退出
    redisClient.quit()
})
  1. const redisClient = redis.createClient(6379, ‘127.0.0.1’,{auth_pass:123456}),注意创建客户端参数
  2. get 和 set 方法的使用

控制台输出:

Reply: OK
val zhangsan2

2.nodejs 连接 redis--封装成工具

conf/db.js

const env = process.env.NODE_ENV //环境变量(package.json中已定义)

// 配置
let MYSQL_CONF
let REDIS_CONF

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

    // redis
    REDIS_CONF = [
        6379,
        '127,0.0.1',
        {
          auth_pass: 123456
        }
    ]
}
// 线上环境配置
if (env === 'production') {
    MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: '123456',
        port: '3306',
        database: 'myblog'
    }
    // redis
    REDIS_CONF = [
        6379,
        '127,0.0.1',
        {
          auth_pass: 123456
        }
    ]
}

module.exports = {
    MYSQL_CONF,
    REDIS_CONF
}

db/redis.js

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

// 创建客户端
const redisClient = redis.createClient(REDIS_CONF[0],REDIS_CONF[1],REDIS_CONF[2])
redisClient.on('error', err => {
    console.log(err)
})

function set(key,val) {
    // 如果是对象类型转为字符串
    if (typeof val === 'object') {
        val = JSON.stringify(val)
    }
    redisClient.set(key,val,redis.print)
}

function get(key) {
    // redisClient.get()有回调,是异步形式,用promise封装
    const promise = new Promise((resolve, reject) => {
        redisClient.get(key, (err,val) => {
            if (err) {
                reject(err)
                return
            }
            // 如果不存在key
            if (val == null) {
                resolve(null)
                return
            }
            // 通过 try  cath 兼容json格式
            try {
                resolve(
                    JSON.parse(val)
                )
            } catch (ex) {
                resolve(val)
            }
            resolve(val)
        })
    })
    return promise
}

module.exports = {
    set,
    get
}

3.redis 使用

app.js
const {get, set} = require('./src/db/redis')
...
    // 解析cookie
    req.cookie = {}
    const cookieStr = req.headers.cookie || ''  //k1=v1;k2=v2;
    cookieStr.split(';').forEach(item => {
        if(!item) {
            return
        }
        const arr = item.split('=')
        const key = arr[0].trim()
        const val = arr[1].trim()
        req.cookie[key] = val
    })
    console.log('req.cookie is',req.cookie)
    
    // 解析session(使用redis)
    let needSetCookie = false //有userId不需设置cookie
    let userId = req.cookie.userid
    if (!userId) {
        needSetCookie = true
        userId = `${Date.now()}_${Math.random()}`
        console.log(userId)
        set(userId,{})
    }
    // 获取session
    req.sessionId = userId
    get(req.sessionId).then((sessionData) => {
        if (sessionData == null) {
            // 初始化 redis 中的 session 值
            set(req.sessionId,{})
        } else {
            // 设置session
            console.log(sessionData)
            req.session = sessionData
        }
    })
    ...
    if (blogResult) {
            blogResult.then(blogData => {
                // 如果需要设置cookie
                if (needSetCookie) {
                    res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
                }
                res.end(
                    JSON.stringify(blogData)
                )
            })
            return
        }
        // 处理 user 路由
        const userResult = handleUserRouter(req,res)
        if (userResult) {
           userResult.then(userData => {
               // 如果需要设置cookie
              if (needSetCookie) {
                res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
              }
              res.end(
                JSON.stringify(userData)
            )
           })
            return
        }
  1. 解析cookie,通过req.headers.cookie获取cookie字符串(k1=v1;k2=v2;),经过一些列操作得到req.cookie is { userid: ‘1602603841727_0.36866137268150534’ }
  2. userId =req.cookie.userid,如果userId不存在则进行随机生成的操作,通过needSetCookie标识并在后面的两个处理路由中通过res.setHeader(‘Set-Cookie’, userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()})返回客户端生成cookie。
  3. req.sessionId = userId,通过调用get方法获取一个promise包裹的对应value(userId作为key),如果为空即redis中没有的话就set(req.sessionId,{}),不为空的话req.session = sessionData(把value值给req.session,别的操作可以通过req.session获取对应的session的value)

登陆:把username和realname作为req.session对象的key和他们的value存储为redis的value
router/user.js

// 登陆
    if (method === 'GET' && 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
                console.log('req.session is',req.session)
                //  同步到redis
                set(req.sessionId, req.session)
                return new SuccessModel()
            }
            return new ErrorModel('登陆失败')
        }) 
    }

4.server端登陆

router/blog.js
// 统一的登陆验证函数
const loginCheck = (req) => {
    if (!req.session.username) {
        return Promise.resolve(new ErrorModel('尚未登陆'))
    }
}

// 获取博客详情
    if (method === 'GET' && req.path ==='/api/blog/detail') {
        const result = getDetail(id)
        return result.then(data => {
            return new SuccessModel(data)
        })
    }

    // 新建一篇博客
    if (method === 'POST' && req.path ==='/api/blog/new') {
        const loginCheckResult = loginCheck(req)
        if (loginCheckResult) {
            // 未登陆
            return loginCheck
        }
        // 由于还没有登陆,需模拟登陆后
        // const author = 'zhangsan'
        const author = req.session.username
        req.body.author = author
        const result = newBlog(req.body)
        return result.then(data => {
            return new SuccessModel(data)
        })
    }

    // 更新一篇博客
    if (method === 'POST' && req.path ==='/api/blog/update') {
        const loginCheckResult = loginCheck(req)
        if (loginCheckResult) {
            // 未登陆
            return loginCheck
        }
        const result = updateBlog(id, req.body)
        return result.then(val => {
            if (val) {
                return new SuccessModel()
            } else {
                return new ErrorModel('更新博客失败')
            }
        })
    }

    // 删除一篇博客
    if (method === 'POST' && req.path ==='/api/blog/delete') {
        const loginCheckResult = loginCheck(req)
        if (loginCheckResult) {
            // 未登陆
            return loginCheck
        }
        // 由于还没有登陆,需模拟登陆后
        const author = req.session.username

        const result = delBlog(id,author)
        return result.then(val => {
            if (result) {
                return new SuccessModel()
            } else {
                return new ErrorModel('删除博客失败')
            }
        })
    }

定义一个统一的登陆验证函数,由于删除、更新、新建都需要登陆,所以在各字路由分别添加上

if (loginCheckResult) {
            // 未登陆
            return loginCheck
        }

由于删除和更新需要author参数,之前用的是写死的,现在可以改为req.session.username获取。

router/user.js

// 登陆
    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
                console.log('req.session is',req.session)
                //  同步到redis
                set(req.sessionId, req.session)
                return new SuccessModel()
            }
            return new ErrorModel('登陆失败')
        }) 
    }

1.把GET改为POST
2.改为从req.body中获取数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值