cookie 和 Session
cookie 做登录校验的过程
- 前端输入用户名密码,传给后端
- 后端验证成功,返回信息时set-cookie
接下来所有接口访问,都自动带上cookie(浏览器的默认行为, http协议的规定)
为何会有 Session?
cookie只存储userld ,不去暴露用户信息
用户信息存储在session中
// session:存储用户信息{"2019283":{username:'jack',age:20}}
Session 优点
原理简单,易于学习
用户信息存储在服务端,可以快速封禁某个登录的用户——有这方强需求的人,一定选择Session
Session 缺点
占用服务端内存,有硬件成本
- 多进程、多服务器时,不好同步 —— 一般使用第三方redis存储,成本高
-
JWT
JWT 的过程
前端输入用户名密码,传给后端
- 后端验证成功,返回一段 token 字符串 – 将用户信息加密之后得到的
- 前端获取token之后,存储下来
-
JWT 的优点
不占用服务器内存
- 多进程、多服务器,不受影响
-
JWT 的缺点
-
JWT 和 Sessiong 的重要区别
JWT用户信息存储在客户端
-
为什么选择JWT ?
没有快速封禁登录用户的需求(或者极少有这种情况)
- JWT成本低,维护简单
- 需要考虑跨域的扩展性(虽然目前还没有这个需求)
使用步骤
- 安装 npm 插件
[koa-jwt](https://www.npmjs.com/package/koa-jwt):jwt会验证所有的路由的请求头有没有token。[jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken):加密,返回一个token;解密,返回解密后的data
```javascript const util = require(‘util’) const jwt = require(‘jsonwebtoken’) const verify = util.promisify(jwt.verify) /**const jwt = require('jsonwebtoken')/*** jwt sign* @param {Object} data data*/function jwtSign(data) {const token = jwt.sign(data, JWT_SECRET, { expiresIn: jwtExpiresIn })return token}
- jwt verify
- @param {string} token token */ async function jwtVerify(token) { const data = await verify(token.split(‘ ‘)[1], JWT_SECRET) // 去掉前面的 Bearer return data }
- **封装 jwt 中间件**,并在app.js文件使用,这样```javascriptconst jwt = require('./middlewares/jwt')// 配置 jwtapp.use(jwt)
const jwtKoa = require('koa-jwt')const { JWT_SECRET, JWT_IGNORE_PATH } = require('../config/constant')module.exports = jwtKoa({secret: JWT_SECRET,cookie: 'jwt_token', // 使用 cookie 存储 token}).unless({// 定义哪些路由忽略 jwt 验证path: JWT_IGNORE_PATH, // 这里忽略了所有,需要登录验证的,自己用 loginCheck中间件})
- 封装 loginCheck 中间件:登录校验,解密用户信息。
```javascript
/**
- @description 登录校验
- @author 双越 */
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 = errResreturn
}
let flag = true try {
const userInfo = await jwtVerify(token)delete userInfo.password // 屏蔽密码// 验证成功,获取 userInfoctx.userInfo = userInfo
} catch (ex) {
flag = falsectx.body = errRes
}
if (flag) {
// 继续下一步await next()
} } ```
- 相关的配置项、构造函数等
SSO 和 OAuth2
- SSo 单点登录
-
使用 Cookie 实现
简单的,如果业务系统都在同一主域名下,比如 wenku.baidu.com tieba.baidu.com ,就好办了。可以直接把cookie domain 设置为主域名 baidu. com ,百度也就是这么干的。
SSO单点登录
复杂一点的,滴滴这么潮的公司,同时拥有didichuxing.com xiaojukeji.com didiglobal.com等域名,种cookie是完全绕不开的。

OAuth第三方登录
上述 SSo 是 oauth的实际案例,其他常见的还有微信登录、github登录等。即,当设计到第三方用户登录校验时,都会使用 OAuth2.0 标准。
- 流程参考 RFC 6749
-
短信验证码登录 用户体验好,无需注册,无需记住密码。
- 但是,它要花钱。而且还要防止攻击,恶意刷接口的。
