JsonWebToken
JWT 英文名是 Json Web Token ,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证。
JWT 以 JSON 对象的形式安全传递信息。因为存在数字签名,因此所传递的信息是安全的。
在单点登录中,当有多个网站提供同一拨服务,那么怎么实现在a网站登录后其他网站也同时登录呐?
在了解jwt之前我们先来说下internet服务的身份验证过程:
客户端向服务器发送登录名和登录密码,服务器验证后将相关信息保存到当前对话中
服务端向客户端返回session,session信息都会写入到客户端的cookie中,后面的请求都会从cookie中读取 Session 发送给服务器,服务器在收到 Session 后会对比保存的数据来确认客户端身份。
但是这种模式存在一个问题,就是需要数据库来保存session绘画,实现服务器之间的会话数据共存,架构修改困难,验证逻辑需要重写,并且整体依赖数据库。如果存储 Session 会话的数据库挂掉那么整个身份认证就无法使用,进而导致系统无法登录
jwt简述
客户端身份经过服务器验证通过后,会生成带有签名的 JSON 对象并将它返回给客户端。客户端在收到这个 JSON 对象后存储起来。
在以后的请求中客户端将 JSON 对象连同请求内容一起发送给服务器,服务器收到请求后通过 JSON 对象标识用户,如果验证不通过则不返回请求的数据。
jwt技术
1.JWT(Json Web Token)是实现token技术的一种解决方案,JWT由三部分组成: header(头)
、payload(载体)
、signature(签名)
。
2.头 HS384 HS512 RS256 RS384 RS512 ES256 ES384 ES512 PS256 PS384
有这几种
3.载体
iss:Issuer,发行者
sub:Subject,主题
aud:Audience,观众
exp:Expiration time,过期时间
nbf:Not before
iat:Issued at,发行时间
jti:JWT ID
-
签名
利用Nodejs搭建简单的Token验证
在控制台下载jwt依赖项
yarn add jsonwebtoken
生成token令牌
生成私钥和公钥后,项目会出现两个文件
function genToken(data){ //非对称加密方式进行token生成? //一般通过私钥进行token加密 //后续前端携带加密后的token给后端,后端再去通过公钥解密token.判别哪个用户身份 //生成私钥:在控制台输入 ssh-keygen -t rsa -b 2048 -f private.key //生成公钥 在控制台输入openssl rsa -in private.key -pubout -outform PEM -out public.key let privateKey = fs.readFileSync(path.resolve(__dirname,"../keys/private.key")) //获取私钥 let token = jwt.sign(data,privateKey,{ expiresIn: ‘24h‘, //token失效时间 algorithm: ‘RS256‘ //加密算法(不设置加密算法,会报错) }) return token } let token = genToken({username:req.body.username}) res.render("api.succ.ejs",{ data:JSON.stringify({message:"恭喜您:登录成功",username:req.body.username,token}) //登录成功后,后端需要产生token令牌给前端返回 })
在点击登录时,把后端返回的token值存到本地存储中
localStorage.setItem("token",result.data.token)
前端验证是否用户登录
verifyLogin() function verifyLogin(){ $.ajax({ url:"/api/user/isloginin", //后端接口 method:"post", headers:{ "X-Access-Token" : localStorage.getItem("token") //请求头 }, dataType:"json", success:data=>{ console.log(data)//经过后端解密之后,看看登录的是哪个用户 } }) }
验证用户是否登录的接口
const isloginin = async(req,res)=>{ //需要从请求头上面获取前端传递来的加密的token let token = req.header("X-Access-Token") //后端需要通过公钥解密token,看看哪个用户 let publicKey = fs.readFileSync(path.resolve(__dirname,"../keys/public.key")) //进行公钥解密 jwt.verify(token, publicKey,(err, authData) => { if(!err){ res.render("api.succ.ejs",{ data:JSON.stringify({username:authData.username}) //把用户名返回给前端 }) }else{ res.render("api.fail.ejs",{ data:JSON.stringify({message:"用户验证失败"}) }) } }) }