node学习(5)身份验证

132 阅读3分钟

身份认证

服务端渲染使用Session认证机制

Cookie

1 键值对,值不超过4kb
2 不同域名下的cookie各自独立
3 有过期时限
4 每次客户发起请求会把当前域名下所有未过期的cookie一同发给服务器

作用

客户端第一次请求服务器时,服务器会通过响应头形式向客户端发送一个身份认证的Cookie,客户端会自动把cookie保存在浏览器中,之后客户端再每次请求服务时,浏览器会自动把身份认证相关cookie以请求头形式发给服务器,服务器进行验证身份,发送身份对应的内容给客户端

提高身份认证安全性--Session认证机制

cookie不具有安全性,不建议把重要隐私数据通过cookie发送

安装express-session中间件

npm i express-session
实例:
// 导入express
const express = require('express')
// 创建express服务器实例
const app = express()

//导入xpress-session中间件
var session = require('express-session')

// 配置session中间件
app.use(session({
    secret: 'my secrect',  //可以为任意值
    resave: false,           //固定写法
    saveUninitialized: true  //固定写法
}))

// 托管静态页面
app.use(express.static('./pages'))
app.use(express.urlencoded({ extended: false }))


// 登录接口——session存数据
app.post('/api/login', (req, res) => {
    if (req.body.username !== 'admin' || req.body.password != '000000') {
        return res.send({
            status: 1,
            msg: '账号密码错误,登陆失败!'
        })
    }

    // 把登陆成功后的用户信息存到session中
    req.session.user = req.body   //存储用户登录信息
    req.session.isLogin = true    //存储登陆状态

    res.send({
        status: 0,
        msg: '登录成功'
    })
})

// 获取用户姓名接口——session取数据
app.get('/api/username', (req, res) => {
    //判断是否登录
    if (!req.session.isLogin) {
        return res.send({
            status: 1,
            msg: '获取失败'
        })
    }

    res.send({
        status: 0,
        msg: '获取成功',
        username: req.session.user.username
    })
})


//退出登录——清空session

app.post('/api/logout', (req, res) => {
    req.session.destroy()
    res.send({
        status: 0,
        msg: '退出登录成功'
    })

})


app.listen(8081, () => {
    console.log('http://127.0.0.1:8081')
})


局限性
需要配合cookie实现,cookie不支持跨域访问,所以涉及到跨域需要做很多额外配置才能实现跨域session认证

前后端分离推荐使用JWT认证机制(token)

header.payload.signature payload:加密后的用户信息 header、signature:安全性相关部分,保证token安全性

推荐把JWT放在http请求头的Authorization字段中 Authorization: Bearer

安装jwt相关包

jsonwebtoken:生成jwt字符串

express-jwt:解析还原jwt字符串(踩坑:安装5.3.3,否则会报错)

命令:npm i jsonwebtoken express-jwt

实例

// 导入express
const express = require('express')
// 创建express服务器实例
const app = express()


//导入jwt中间件
var jwt = require('jsonwebtoken')
var expressJWT = require('express-jwt')



// 托管静态页面
// app.use(express.static('./pages'))
// 解决跨域
const cors = require('cors')
app.use(cors())

const parser = require('body-parser')
app.use(parser.urlencoded({ extended: false }))

// 定义secret密钥 本质就是定义一个字符串
const secretKey = 'my test key'


// 配置解析jwt还原成json
// 解析token:expressJWT({secret:secretKey})
// .unless({path:[/^\/api\//]})  用来指定哪些接口不需要访问权限
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))



// 登录接口——生成jwt字符串
app.post('/api/login', (req, res) => {

    const userinfo = req.body
    if (userinfo.username !== 'admin' || userinfo.password != '000000') {
        return res.send({
            status: 400,
            msg: '账号密码错误,登陆失败!'
        })
    }

    //    登陆成功生成jwt字符串,通过token传给用户
    const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
    res.send({
        status: 0,
        msg: '登录成功',
        // 调用jwt.sign(生成jwt字符串,三个参数:用户信息对象,加密密钥,配置对象(配置token有效期 30秒)
        token: tokenStr
    })
})

// 获取用户信息接口——还原jwt
app.get('/admin/getinfo', (req, res) => {

    // 配置成功express-jwt中间件会把解析出来的用户信息,挂载到req.user属性上

    // postman测试时发送请求头Authorization: Bearer <token>
    console.log(req.user)

    res.send({
        status: 0,
        msg: '获取成功',
        data: req.user
    })
})

// 使用全局错误处理中间件,捕获JWT失败产生的错误
app.use((err, req, res, next) => {
    // UnauthorizedError:token解析失败错误
    if (err.name === 'UnauthorizedError') {
        return res.send({
            status: 401,
            message: '无效的token'
        })
    }
    res.send({
        status: 500,
        message: '未知的错误'
    })
})

app.listen(8081, () => {
    console.log('http://127.0.0.1:8081')
})