nodejs的基本使用(四)身份认证Session,JWT

web开发模式

目前有两个主流:

  1. 服务端渲染
  2. 前后端分离

服务端渲染:服务器发给客户端html页面,在服务器端通过拼接,动态生成。所以客户端不需要使用ajax技术。

优点:前端耗时少,有利于seo

缺点:占用服务器资源,不利于前后分离,开发效率低

前后端分离:依赖于ajax

优点:开发体验好,用户体验好,减轻了服务端的渲染压力。

缺点:不利于网站的seo

身份认证

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

前后分离使用JWT认证机制

Session认证机制

http协议无状态性:就是发送多次请求,服务器不会保留上一次的状态。

现实生活中会员卡身份认证,在web中叫做Cookie,Cookie是存放浏览器的字符串,由名称,值等组成 用于控制Cookie有效期,安全性,使用范围的可选属性组成。session认证不适合跨域认证。

下面使用Session认证:

# 安装
yarn add express-session
// app.js

const express = require('express')
const cors = require('cors')
// 导入session
const session = require('express-session')
// 创建app
const app = express()

// 注册中间件
app.use(express.static('./pages'))
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
// 使用session 固定写法
app.use(
  session({
    secret: 'zxc', // 任意字符 密钥
    resave: false,
    saveUninitialized: true
  })
)

// 登录
app.post('/api/login', (req, res) => {
  if (req.body.username !== 'admin' || req.body.password !== '000') {
    return res.send({ status: 1, msg: '登陆失败' })
  }
  // 登陆成功后的用户信息 保存到session中
  req.session.user = req.body //用户信息
  req.session.islogin = true //登陆状态
  res.send({
    statu: 0,
    msg:'登陆成功'
  })
})

// 获取session中的数据
app.get('/api/username', (req, res) => {
  if (!req.session.islogin) {
    return res.send({ status: 1, meg: 'fail' })
  }
  res.send({ status: 0, data: req.session.username })
})

// 退出登录清空session
app.post('/api/logout', (req, res) => {
  req.session.destroy() //只会清空当前用户的session
  res.send({ status: 0, msg: '退出成功' })
})

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

JWT认证机制

jwt工作原理:客户端提交账户密码发送给服务端,服务端验证账号密码通过后会返回给客户端一个token字符串,客户端拿到之后进行本地存储。等再一次登陆时,直接使用本地存储的token字符串进行登录就实现了免密登录。

jwt字符串由 header payload signature组成,payload部分才是真正的用户信息,其他两部分只为了保证token的安全性。

下面是jwt的使用方式:

拿到token后,每次请求服务器都在请求头带上token字段,推荐做法:

// 设置请求头 Authorization字段
Authorization: Bearer <token>

安装

yarn add jsonwebtoken express-jwt

jsonwebtoken:可以生产token字段

express-jwt:用于将jwt字符串解析还原成json对象,当我们配置了之后,那么req.user就是存储的是当前解析token中的数据,就可以使用req.user获取。

// app.js
const express = require('express')
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
const bodyParser = require('body-parser')
// 创建app
const app = express()
// 注册中间件
app.use(bodyParser.urlencoded({ extended: false }))
const secretKey = 'test-01' //定义secretKey密钥
// 解析token 需要secretKey密钥,algorithms为['HS256'] unless中的path可以指定不需要token验证的接口
app.use(
  // 配置了express-jwt中间件 就可以把解析出来的用户信息挂载到 req.user上
  expressJWT({ secret: secretKey, algorithms: ['HS256'] }).unless({
    path: [/\/api\/login/]
  })
)

// 登录接口
app.post('/api/login', (req, res) => {
  const { username, password } = req.body
  if (username !== 'admin' || password !== '000') {
    return res.send({ status: 1, msg: '登陆失败' })
  }
  // jwt.sign() 生成token
  // 参数一:用户信息对象
  // 参数二:加密的密钥
  // 参数三:配置对象,可以配置token有效期
  // 千万不要把密码加密到字符串中,否则就危险了
  const token = jwt.sign({ username }, secretKey, {
    expiresIn: '30s'
  })
  res.send({
    status: 200,
    msg: '登陆成功',
    token
  })
})
// expressJWT 解析token字符串并获取
app.get('/api/getinfo', (req, res) => {
  console.log(req.user)
  res.send({
    status: 200,
    msg: '获取用户信息成功',
    data: req.user
  })
})

// 捕获token验证错误中间件
app.use((err, req, res, next) => {
  if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      msg: '无效的token'
    })
  }
  res.send({
    status:500,
    msg:'未知的错误'
  })
})

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


版权声明:本文为weixin_52907628原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。