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 beforeiat: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.keylet 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)=>{//需要从请求头上面获取前端传递来的加密的tokenlet 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:\"用户验证失败\"})})}})}