首页
学习
活动
专区
圈层
工具
发布
50 篇文章
1
【架构师(第一篇)】整体需求分析和架构设计
2
【架构师(第二篇)】脚手架架构设计和框架搭建
3
【架构师(第三篇)】脚手架开发之掌握Lerna操作流程
4
【架构师(第四篇)】脚手架开发之Lerna源码分析
5
【架构师(第五篇)】脚手架之import-local执行流程及简历设计
6
【架构师(第六篇)】脚手架之需求分析和架构设计
7
【架构师(第七篇)】脚手架之准备阶段编写
8
【架构师(第八篇)】脚手架之 commander 框架使用方法
9
【架构师(第九篇)】如何让 Node 环境支持 ES Module
10
【架构师(第十篇)】脚手架之注册命令及架构优化
11
【架构师(第十一篇)】脚手架之命令注册和执行过程开发
12
【架构师(第十二篇)】脚手架之命令行交互工具 inquirer.js 使用方法
13
【架构师(第十三篇)】脚手架之创建项目准备阶段开发
14
【架构师(第十四篇)】脚手架之 egg.js 和 mongodb 的使用
15
【架构师(第十五篇)】脚手架之创建项目模板开发
16
【架构师(第十六篇)】脚手架之创建项目模板的下载与更新
17
【架构师(第十七篇)】脚手架之 ejs 和 glob 的使用
18
【架构师(第十八篇)】脚手架之项目模板的安装
19
【架构师(第十九篇)】脚手架之组件库模板开发
20
【架构师(第二十篇)】脚手架之自定义模板及第一阶段总结
21
【架构师(第二十一篇)】编辑器开发之需求分析和架构设计
22
【架构师(第二十二篇)】编辑器开发之项目整体搭建
23
【架构师(第二十三篇)】编辑器开发之画布区域组件的渲染
24
【架构师(第二十四篇)】编辑器开发之添加模版到画布
25
【架构师(第二十五篇)】编辑器开发之属性编辑区域表单渲染
26
【架构师(第二十六篇)】编辑器开发之属性编辑同步渲染
27
【架构师(第二十七篇)】前端单元测试框架 Jest 基础知识入门
28
【架构师(第二十八篇)】 测试工具 Vue-Test-Utils 基础语法
29
【架构师(第二十九篇)】Vue-Test-Utils 触发事件和异步请求
30
【架构师(第三十篇)】Vue-Test-Utils 全局组件和第三方库 vuex | vue-router
31
【架构师(第三十一篇)】前端测试之 TDD 的开发方式
32
【架构师(第三十二篇)】 通用上传组件开发及测试用例
33
【架构师(第三十三篇)】 Vue 中的实例及本地图片预览
34
【架构师(第三十四篇)】 业务组件库开发之 vue3 的插件系统
35
【架构师(第三十五篇)】 业务组件库开发之使用 Rollup 进行打包
36
【架构师(第三十六篇)】 业务组件库开发之发布到 NPM
37
【架构师(第三十七篇)】 服务端开发之后端框架与数据库技术选型
38
【架构师(第三十八篇)】 服务端开发之本地安装最新版 MySQL 数据库
39
【架构师(第三十九篇)】 服务端开发之连接 MySQL 数据库
40
【架构师(第四十篇)】 服务端开发之连接 Mongodb 数据库
41
【架构师(第四十一篇)】 服务端开发之安装并连接 Redis数据库
42
【架构师(第四十二篇)】 服务端开发之常用的登录鉴权方式
43
【架构师(第四十三篇)】 服务端开发之单元测试和接口测试
44
【架构师(第四十四篇)】 服务端开发之 pm2 和 nginx 介绍
45
【架构师(第四十五篇)】 服务端开发之认识 Github actions
46
【架构师(第四十六篇)】 服务端开发之安装 Docker
47
【架构师(第四十七篇)】 服务端开发之认识 Docker
48
【架构师(第四十八篇)】 服务端开发之 Dockerfile
49
【架构师(第四十九篇)】 服务端开发之认识 Docker-compose
50
【架构师(第五十篇)】 服务端开发之自动发布到测试机
清单首页架构文章详情

【架构师(第四十二篇)】 服务端开发之常用的登录鉴权方式


内容概括

主要产出

  • 了解 Web 常用的登录鉴权方式

主要内容

  • cookiesession
  • JWT
  • SSOOAuth2

关于短信验证码

  • 用户体验好,无需注册,无需记住密码
  • 验证码需要收费,所以需要防止恶意共计,恶意刷接口

介绍 Session 登录

cookie 做登录校验的过程

  • 前端输入用户名密码,传给后端
  • 后端验证成功,返回信息时 set-cookie
  • 接下来的所有接口访问,都自动带上 cookie

为何会有 Session

  • cookie 只存储 userId,不暴露用户信息
  • 用户信息存储在 session

Session 的优点

  • 原理简单,易于学习
  • 用户信息存储在服务端,可以快速封禁某个登录的用户

Session 的缺点

  • 占用服务端内存,有硬件成本
  • 多进程,多服务器时,不好同步,一般使用第三方 redis 存储,成本高
  • 跨域传递 cookie,需要特殊配置

介绍 JWT 登录

JWT 的全称是 JSON Web Token

JWT 的过程

  • 前端输入用户名密码,传递给后端
  • 后端验证成功,返回一段 token 字符串,将用户信息加密之后得到的结果
  • 前端获取 token 之后,存储下来
  • 以后访问接口,都在 header 中携带这段 token

JWT 的优点

  • 不占用服务器内存
  • 多进程,多服务器,不受影响
  • 不受跨域限制

JWT 的缺点

  • 无法快速封禁登录的用户

JWT 和 Session 的重要区别

  • JWT 用户信息存储在客户端
  • Session 用户信息存储在服务器端

为何选择 JWT

  • 没有快速封禁登录用户的需求
  • JWT 成本低,维护简单
  • 需要考虑跨域的扩展性

代码演示

  • 安装 npm 插件,koa-jwtjsonwebjson
  • 封装 jwt 中间件,并使用
  • 封装 loginCheck 中间件
  • 相关的配置项,构造函数等

安装插件

代码语言:javascript
复制
npm i koa-jwt jsonwebtoken -S

封装 jwt 中间件

增加配置

代码语言:javascript
复制
// src\config\constant.js

module.exports = {
  // jwt 秘钥
  JWT_SECRET: 'warbler_for-json#web$token',

  // jwt 忽略默认验证的 path:全部忽略即可,需要登录验证的,用自己封装的 loginCheck
  JWT_IGNORE_PATH: [/\//],
}

封装中间件

代码语言:javascript
复制
//  src\middlewares\jwt.js

const jwtKoa = require('koa-jwt')
const { JWT_SECRET, JWT_IGNORE_PATH } = require('../config/constant')

const jwt = jwtKoa({
  secret: JWT_SECRET, // jwt 秘钥
  cookie: 'jwt_token', // 使用 cookie 存储 token
}).unless({
  // 定义哪些路由忽略 jwt 验证
  path: JWT_IGNORE_PATH,
})

module.exports = jwt

使用

代码语言:javascript
复制
// src\app.js

const jwt = require('./middlewares/jwt')
// 配置 jwt 中间件
app.use(jwt)

封装 JWT 工具

代码语言:javascript
复制
// src\utils\jwt.js

const util = require('util')
const jwt = require('jsonwebtoken')

// jwt 密钥
const { JWT_SECRET } = require('../config/constant')

// jwt 过期时间
const { jwtExpiresIn } = require('../config/index')

const verify = util.promisify(jwt.verify)

/**
 * jwt verify  解密
 * @param {string} token token
 */
async function jwtVerify(token) {
  const data = await verify(token.split(' ')[1], JWT_SECRET) // 去掉前面的 Bearer
  return data
}

/**
 * jwt sign  加密
 * @param {Object} data data
 */
function jwtSign(data) {
  const token = jwt.sign(data, JWT_SECRET, { expiresIn: jwtExpiresIn })
  return token
}

// 导出解密,加密两个方法
module.exports = {
  jwtVerify,
  jwtSign,
}

封装 loginCheck 中间件

封装数据模型

代码语言:javascript
复制
// src\res-model\index.js

/**
 * 基础模型,包括 errno data 和 message
 */
class BaseRes {
  constructor({ errno, data, message }) {
    this.errno = errno
    if (data) {
      this.data = data
    }
    if (message) {
      this.message = message
    }
  }
}

/**
 * 执行失败的数据模型
 */
class ErrorRes extends BaseRes {
  constructor({ errno = -1, message = '', data }, addMessage = '') {
    super({
      errno,
      message: addMessage
        ? `${message} - ${addMessage}` // 有追加信息
        : message,
      data,
    })
  }
}

/**
 * 执行成功的数据模型
 */
class SuccessRes extends BaseRes {
  constructor(data = {}) {
    super({
      errno: 0,
      data,
    })
  }
}

module.exports = {
  ErrorRes,
  SuccessRes,
}

封装错误信息集合

代码语言:javascript
复制
// src\res-model\failInfo\error.js

module.exports = {
  // 统一错误处理
  serverErrorFailInfo: {
    errno: -1,
    message: '运行错误',
  },
  // 404
  notFoundFailInfo: {
    errno: -2,
    message: '404 Not Found',
  },
}

封装中间件

代码语言:javascript
复制
// src\middlewares\loginCheck.js

// 解密
const { jwtVerify } = require('../utils/jwt')
// 执行失败的数据模型
const { ErrorRes } = require('../res-model/index')
// 错误信息集合
const { loginCheckFailInfo } = require('../res-model/failInfo/index')

/**
 * 登录校验
 * @param {Object} ctx ctx
 * @param {function} next next
 */
module.exports = async function loginCheck(ctx, next) {
  // 失败信息
  const errRes = new ErrorRes(loginCheckFailInfo)

  // 获取 token
  const token = ctx.header.authorization
  if (!token) {
    ctx.body = errRes
    return
  }

  let flag = true
  try {
    const userInfo = await jwtVerify(token)
    delete userInfo.password // 屏蔽密码

    // 验证成功,获取 userInfo
    ctx.userInfo = userInfo
  } catch (ex) {
    flag = false
    ctx.body = errRes
  }

  if (flag) {
    // 继续下一步
    await next()
  }
}

介绍 SSO 和 OAuth2

  • SSO 单点登录
  • OAuth2 第三方鉴权

使用 cookie 实现单点登录

简单的,如果业务系统都在同一主域名下,比如 wenku.baidu.comtieba.baidu.com ,就可以直接把 cookie domain 设置为主域名 baidu.com ,百度也就是这么干的

SSO

OAuth2

SSOOAuth2 的实际案例,其他常见的还有微信登录,github 登录等,当涉及到第三方用户登录校验时,都会使用 OAuth2 标准。

下一篇
举报
领券