JsonWebToken

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
  1. 签名

    利用Nodejs搭建简单的Token验证

    在控制台下载jwt依赖项 yarn add jsonwebtoken

    生成token令牌

    生成私钥和公钥后,项目会出现两个文件

    image-20200809191902839

    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:"用户验证失败"})
                })
            }
        })
    }
    
posted @ 2020-08-09 19:31  Cupid05  阅读(109)  评论(0编辑  收藏  举报