nodejs实现登录功能

136 阅读2分钟

Cookie

一、cookie 介绍及客户端操作cookie

image.png

image.png

image.png

image.png

image.png

JS操作cookie, 浏览器中查看cookie :

image.png

二、 server 端操作cookie, 实现登录验证

1、server获取cookie的值并解析cookie

// 解析 cookie
req.cookie = {}
const cookieStr = req.headers.cookie || ''  // k1=v1;k2=v2;k3=v3
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
})

2、server端修改 cookie

res.setCookie('Set-cookie', username='Lisa')

3、实现登录验证

image.png

// 登录验证的测试- 如果cookie中有username, 则登录成功
if (method === 'GET' && req.path === '/api/user/login-test') {
    if (req.cookie.username) {
        return Promise.resolve(
            new SuccessModel({
                session: req.session
            })
        )
    }
    return Promise.resolve(
        new ErrorModel('尚未登录')
    )
}

4、server端对cookie 做限制

设置完httpOnly后,客户端就没有权限对cookie进行修改了;

res.cookie('Set-cookie', username=${username}; path=/;httpOnly);

5、设置cookie的过期时间

为了安全起见,过一段时间,让用户重新登录一次

// 获取 cookie 的过期时间
const getCookieExpires = () => {
    const d = new Date()
    d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
    console.log('d.toGMTString() is ', d.toGMTString())
    return d.toGMTString()
}

然后,server端对cookie设置过期时间:expires = xxx

res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)

三、cookie总结

总结一: 使用cookie 做登录验证,例如判断cookie中如果有username存在,就便是登录了,这样子会暴漏username,有危险;

解决办法: cookie中存储userid,server端对应username;

总结二:cookie的内存大小只有5KB,可以存储的信息也有限;

Session

一、 session 介绍

image.png

// 解析 session
let needSetCookie = false
let userId = req.cookie.userid
if (userId) {
    if (!SESSION_DATA[userId]) {
        SESSION_DATA[userId] = {}
    }
} else {
    needSetCookie = true
    userId = `${Date.now()}_${Math.random()}`
    SESSION_DATA[userId] = {}
}
req.session = SESSION_DATA[userId]
// 登录验证的测试
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('尚未登录')
    )
}

二、总结

session 解决什么问题,cookie不满足的,session满足; session 如何使用?

image.png

image.png

如何解决 session 的问题呢?redis;

Redis

Redis是内存数据库, mysql是硬盘数据库(使用B树算法);

image.png

image.png

image.png

image.png

image.png

1、redis 安装与使用

安装教程

启动redis :

redis-cli.exe -h 127.0.0.1 -p 6379

使用方法: 设置key: set 变量名 变量值

image.png

查看所有的key: keys *

image.png

删除指定的 key: del 变量名

2、nodejs 连接 redis 的demo

首先在项目中安装 redis: npm i redis --save

启动redis服务命令:

redis-server.exe redis.windows.conf

image.png 另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端 运行:

redis-cli.exe -h 127.0.0.1 -p 6379
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()
})

image.png

3、nodejs 连接 redis 封装函数

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

// 创建客户端
const redisClient = redis.createClient(REDIS_CONF)
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)
            }
            // 退出
            redisClient.quit()
        })
    })
    return promise
}

module.exports = {
    set,
    get
}