Cookie
HTTP
协议的无状态性HTTP协议的无状态:
客户端的每次HTTP请求都是独立的,之间没有直接关系
服务器不会主动保留每次HTTP请求的状态
HTTP
无状态的限制发会员卡
注意:
现实中,会员卡身份认证方式,在Web开发中的专业术语叫做
Cookie
Cookie
Cookie
是存储在用户浏览器中的一段不超过4KB
的字符串
不同域名下的Cookie
各自独立
每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie
一同发送到服务器进行身份验证
特点:
- 自动发送
- 域名独立
- 过期时限
4KB
限制
Cookie
在身份认证中的作用Session
会员卡+刷卡认证,就是Session
认证机制的精髓
Session
工作原理Express
中使用Session
认证npm install express-session
express-session
中间件//导入session 中间件
var session = require('express-session')
//配置Session中间件
app.use(session({
secret:"keyboard cat", //secret 属性的值可以为任意字符串
resave: false, //固定写法
saveUninitialized: true //固定写法
}))
session
中存数据express-session
中间件配置成功
可通过 req.session
来访问和使用 session
对象
存储用户的关键信息
app.post('/api/login',(req,res)=>{
//判断用户提交的登录信息是否正确
if(req.body.username !== 'admin' || req.body.password !== '00000'){
return res.send({status: 1,msg:'登录失败'})
}
req.session.user = req.body //将用户信息,存储到Session中
req.session.islogin = true //将用户登录状态,存储到Session中
res.send({status:0,msg:'登录成功'})
})
session
中取数据//获取session中取数据
app.get('/api/username',(req,res)=>{
//判断用户是否登录
if(!req.session.islogin){
return res.send({status:1,msg:'fail'})
}
res.send({status:0,msg:'success',username:req.session.user.username})
})
session
//退出登录的接口
app.post('/api/logout',(req,res)=>{
//清空当前客户端对应的session信息
req.session.destroy()
res.send({
status:0,
msg:'退出登录成功'
})
})
JWT
Session
认证的局限性Session
认证机制需要配合Cookie
才能实现
Cookie
默认不支持跨域访问(需要额外配置)
JWT
JWT
(JSON
Web Token
) 是目前最流行的跨域认证解决方案
JWT
工作原理用户的信息通过
Token
字符串的形式,保存在客户端浏览器中
JWT
的组成部分JWT
由三部分组成:
Header
(头部)--------------------->安全性相关
Payload
(有效荷载)-------------->用户信息加密后的字符串
Signature
(签名)------------------>安全性相关
Header.Payload.Signature
JWT
的使用方式客户端收到服务器返回的JWT
之后
通常存储在localStorage
或sessionStorage
中
客户端每次通信都要带上这个JWT
字符串,进行身份认证
(推荐把JWT
放在HTTP
请求头的Authorization
字段中)
Authorization:Bearer
Express
中使用JWT
JWT
相关的包npm install jsonwebtoken express-jwt
jsonwebtoken
用于生成JWT
字符串
express-jwt
用于将JWT
字符串解析还原成JSON
对象
JWT
相关的包//导入用于生成JWT字符串的包
const jwt = require('jsonwebtoken')
//导入用于将客户端发送过来的JWT字符串,解析还原成JSON对象的包
const experssJWT = require('express-jwt')
JWT
字符串//自定义
const secretKey = 'itheima No1 ^_^'
//登录接口
app.post('/api/login',function(req,res){
//用户登录成功之后,生成JWT字符串,通过token属性响应给客户端
res.send({
status:200,
message:'登录成功',
//调用jwt.sign()生成JWT字符串,三个参数分别是:用户信息对象,加密密钥,配置对象
token:jwt.sign({username:userinfo.useranme},secretKey,{expiresIn:'30s'})
})
})
JWT
字符串还原为JSON
对象客户端每次访问那些有权限接口的时候
都需要主动通过请求头中的Authorization
字段
服务器可以通过express-jwt
中间件,将客户端发送过来的token
解析还原成JSON
对象
//使用app.use() 来注册中间件
//expressJWT ({secret:secretKey}) 就是用来解析Token 的中间件
//.unless({path:[//^\/api\//]}) 用来指定哪些接口不需要访问权限
app.use(expressJWT({secret:secretKey}).unless({path:[//^\/api\//]}))
req.auth
获取用户信息当express-jwt
这个中间件配置成功之后
即可使用req.user
对象,访问解析出来的用户信息
//这个是一个有权限的API接口
app.get('/admin/getinfo',function(req,res){
console.log(req.auth)
res.send({
status:200,
message:'获取用户信息成功!',
data:req.auth
})
})
JWT
失败后产生的错误如果客户端发送过来的Token
字符串过期或不合法
会产生一个解析失败的错误
app.use(err,req,res,next){
//token解析失败导致的错误
if(err.name === 'UnauthorizedError'){
return res.send({status:401,message:'无效的token'})
}
//其它原因导致的错误
res.send({status:500,message:'未知错误'})
}