Express身份验证
- 在平常我们使用网站时,只需要登录一次即可,之后再访问这个网站就不需要再进行登录操作,本文将介绍Express中的session和token,它们是进行身份验证方法。
- HTTP 是一种没有状态的协议,也就是它并不知道具体是谁,哪一个用户访问。客户端的用户名密码通过了身份验证,不过下回这个客户端再发送请求时,还需要再进行验证。
- 本文的身份验证省略了在数据库中对比的操作,默认请求接口即为登录成功。
session
思想
1、客户端用户名跟密码请求登录
2、服务端收到请求,去库验证用户名与密码
3、验证成功后,服务端种一个cookie或发一个字符到客户端,同时服务器保留一份session
4、客户端收到 响应 以后可以把收到的字符存到cookie
5、客户端每次向服务端请求资源的cookie会自动携带,这个操作由前端完成
6、服务端收到请求,然后去验证cookie和session,如果验证成功,就向客户端返回请求的库数据
代码
- 1.初始化
npm init -y
- 2.安装引入express
npm i express
- 3.安装引入中间件cookie-session
npm i cookie-session
- 4.配置中间件
- 5.进行各种操作
- 在客户端种cookie,备份session
req.session.key=value
- 读cookie对比session
req.session.key
返回值为true
说明身份验证通过 - 除cookie、session
delete req.session.key
req.session.key = undefined
- 在客户端种cookie,备份session
- 6.模拟登录、验证、退出登录操作
// 引入express 和 cookie-session中间件
const express=require('express')
const cookieSession=require('cookie-session')
// 搭建服务器
const server=express()
// 静态资源托管 后面填写静态资源目录
server.use(express.static('./WWW'))
// 监听端口
server.listen(3000)
// 配置中间件
server.use(cookieSession({
name:'mycookie', //后端给前端种的cookie 名字 如果不写默认为 express:sess
keys:['aaa'],//加密层级 一定要填写 否则报错
maxAge:1000*30 //cookie的失效时间 毫秒为单位 30秒后失效
}))
// 设置登录接口 验证用户身份 登录成功后 在前端种 cookie
server.get('/api/login',(req,res)=>{
// 1.检验客户端传来的用户名密码是否与数据库中的一致 省略步骤 默认正确
// 2.给客户端种cookie 服务端保留一份session
req.session.code='userId'
// 3.后端种完cookie 给前端返回数据
res.send({
err:0,
msg:'恭喜您,登录成功!',
data:{
username:'王富贵'
}
})
})
// 验证接口 判断用户是否登录 即验证cookie和session
server.get('/api/user',(req,res)=>{
//如果 验证成功 返回 req.session.code 的值为 登录时设置的'userId'
let pass=req.session.code
if(pass){
res.send({
err:0,
data:'用户已经登录',
})
}else{
res.send({
err:1,
data:'用户未登录或登录过期了',
})
}
})
// 退出登录
server.get('/api/loginout',(req,res)=>{
//两种方式 删除cookie,session
delete req.session.code
// req.session.code=undefined
res.send({
err:0,
data:'退出登录成功'
})
})
运行
- 登录
- 验证是否登录
- 退出登录
- 验证是否登录
token
思想
- 与session的不同
- 在服务端不需要存储用户的登录记录,全部发给客户端有客户端自己存(cookie,local)
- 步骤
1、客户端使用用户名跟密码请求登录
2、服务端收到请求,去验证用户名与密码
3、验证成功后,服务端会签发一个 Token(加了密的字符串),再把这个 Token 发送给客户端
4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token (前端操作)
6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
代码
-
1.初始化
npm init -y
-
2.安装引入express
npm i express
-
3.安装引入中间件jsonwebtoken
npm i jsonwebtoken
-
4.配置中间件
-
5.进行各种操作
- 生成签名
let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])
payload
: json 还有username,useridsecretOrPrivateKey
: 加密规则,字符串,或者私钥path模块options
: 可选配置项callback
: 成功回调, 可选 返回制作后的token,也可同步返回
- 校验token
jwt.verify(token, secretOrPublicKey, [options, callback])
token
: 制作后的tokensecretOrPublicKey
: 解密规则,字符串,或者公钥
-callback
:回调 err 错误信息 decode 成功后的信息options
: expiresIn 过期时间
- 生成签名
-
6.模拟登录、验证、退出登录操作
const express=require('express')
//使用 req.body post的请求的数据 需要用到body-parser中间件
const bodyParser=require('body-parser')
//引入 jsonwebtoken模块
const jwt=require('jsonwebtoken')
const server=express()
server.use(express.static('./WWW'))
server.listen(3000)
// 使用中间件boy-parser
server.use(bodyParser())
// 登录 服务端生成token令牌
server.get('/api/login',(req,res)=>{
// 1.获取用户名,密码进行数据库验证 默认成功
// 2.生成token令牌
let token=jwt.sign({
//前端传递的用户名
username:req.query.username
// 'aaa'加密规则 解密时也按照这个规则
},'aaa',{
//过期时间 以秒为单位
// expiresIn:60 // 过期时间 60秒
})
// 3.将token传给前端 前端把存储起来
res.send({
err:0,
msg:'登录成功',
token
})
})
// 验证登录
server.get('/api/user',(req,res)=>{
//1.获得前端传递来的token 可以是get,post请求传递 也可以在请求头
let token=req.query.token || req.body.token || req.headers.token;
//2.token 检验token
jwt.verify(token,'aaa',(err,decode)=>{
console.log('err',err) //null 表示没有报错
console.log('decode',decode)
if(!err){
// 没有报错 数据返回给前端
res.send({
err:0,
data:'用户登录成功'
})
}else{
//报错 说明登录失败
res.send({
err:1,
data:'登录失败,token失效了'
})
}
})
})
// 退出登录
// 由前端操作 删除存储的 token
运行
- 登录
- 验证登录 将token放在
req.query.token
- 退出登录
session与token
- session服务端保存用户信息,token不是
- token安全性更高
- session存在多服务器粘性问题
- 当在应用中进行 session的读,写或者删除操作时,会有一个文件操作发生在操作系统的temp 文件夹下,至少在第一次时。假设有多台服务器并且 session 在第一台服务上创建。当你再次发送请求并且这个请求落在另一台服务器上,session 信息并不存在并且会获得一个“未认证”的响应。你可以通过一个粘性 session 解决这个问题。然而,在基于 token 的认证中,这个问题很自然就被解决了。没有粘性 session 的问题,因为在每个发送到服务器的请求中这个请求的 token 都会被拦截
转载:https://blog.csdn.net/k464746/article/details/104845520
查看评论