由于 用户进行访问 浏览器时,需要完成对用户身份的确认。称为身份验证,或者“鉴权”和“身份认证”。需要身份认证使用 session认证机制 或者 JWT 认证机制。
由于开发模式不同,身份认证也不同。
对于服务器渲染和前后端分离这两种开发模式来说,分别有不同的身份认证:
- 服务端渲染:即前后端不分离,推荐使用 session 认证机制,有利于 SEO,不存在跨域。
- 前后端分离:推荐使用 JWT 机制,在后台加载速度快。可以跨域
一、session 认证机制
由于 HTTP 协议 是无状态性(每次HTTP 请求都是独立的,多个HTTP请求没有直接关系,服务器不会主动保留每次HTTP请求的状态),所以解决这一无状态的限制,需要一个身份认证的方式进行存储识别,在Web开发的专业属于叫做 Cookie。session 认证机制 需要 配合 cookie 才能实现。
1. cookie
cookie 是 存储在 用户浏览器中不超过 4kb 的字符串。
是由键值对的方式,和其他用于控制 cookie 的有效期,安全性,使用范围的可选属性存在。
客户端第一次请求服务器时,服务器通过响应头的形式,会将未过期的cookie自动发送到客户端,自动存储在客户端,每次都请求携带cookie;客户端通过 请求头,自动将 cookie 发送给服务器,服务器就可以验证客户端的身份;再响应到客户端。
- cookie 存储在 客户端,而且 客户端提供了 读写cookie 的API,因此就很容易被伪造。
- 应用场景
- 保存用户上次登录的信息
- 用户的自动登录(或者记住密码)
- 上一次浏览的信息
- 应用场景
2. Session 的工作原理
- 由于 cookie 的安全性不高,所以使用 session 认证机制。
- 将用户信息存储到 服务器的内存中,之后会生成对应的 cookie 字符串中,将生成的cookie相应到客户端。然后客户端再次发起请求,执行上面cookie相关的操作。
- session 是在 cookie 的基础上进行。
2.1 express-session 实现 session 机制
- npm i express-session
- 配置 session 中间件
- 向 session 中 存储数据,通过 req.session 访问 和 使用 session 对象
- 从 session 中 获取数据,直接从 req.session 对象上 获取之前存储的数据
- 清空 session ,使用 req.session.destory() 函数,就可以清空服务器保存的 session 信息
二、JWT 认证机制
由于 session 认证机制 需要配合cookie才能实现,cookie 默认不支持跨域访问,所以,当涉及前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域 session 认证。
- 当前端请求后端接口不存在 跨域问题的时候,推荐使用 session 身份认证机制
- 当前端需要 跨域 请求后端接口的时候,不推荐使用 session 身份认证机制,推荐使用 JWT 认证机制。
1. 什么是 JWT
JWT 是目前 最流行的跨域认证解决方案。
JWT 有 三个部分,都代表各自的含义。
Header.Payload.Signature
// 其中 Header 头部,Payload 有效荷载,Signature 签名
Payload 部分才是真正的用户的信息,它是用户信息经过加密之后生成的字符串
Header、Signature 是安全性相关的部分,只是为了保证 token 的安全性
2. JWT 工作原理
2.1. express-jwt 实现 JWT 机制
客户端收到服务器返回的 JWT 之后,通常会将 token 值存储到
Local Storage 或者 Session Storage 中。
此后,客户端每次和服务器通信,都要带上 JWT。
推荐做法:
Authorization :Bearer <token>
- npm i jsonwebtoken express-jwt
- 导入 JWT 相关的包
- const jwt = require(‘jsonwebtoken’)
- const expressJWT = require(‘express-jwt’)
- 定义 secret 密钥
- const secretKey = ‘itheima No1 _’
- 在登陆成功后,生成 token 字符串
- 调用 jsonwebtoken包提供的 sign() 方法,将用户信息加密成 JWT字符串。千万不要将密码加密到 token 字符中
- jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: ‘30s’ })
- 注册,将 JWT 字符串还原为 JSON 对象的中间件(解密)
- app.use(expressJWT({ secret: secretKey }).unless({ path: [/^/api//] }))
- 其中 unless 是除了某个页面不进行 生成token字符串