JWT的token登录详解及项目实操流程

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

总结:JWT就是token,它是生成token,校验token的一种工具。常用于分布式站点的单点登录

首先了解一下,基于token的登录流程

1. 客户端使用用户名跟密码请求登录
2. 服务端收到请求,去验证用户名与密码
3. 验证成功后,服务端会签发一个Token,再把这个 Token 发送给客户端
4. 客户端收到Token 以后可以把它存储起来,比如放在 Cookie 里或者 localStorage 里
5. 客户端每次向服务端请求资源的时候需要带着服务端签发的Token
6. 服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据,另外服务端要支持CORS(跨来资源共享)的策略

接下来进入正题------------------------------------------------------------------------------------------------------↓

项目的实操流程

1.初始化一个项目

npm init -y //生成package.json文件

2.下载所需依赖,生成node_modules文件和package-lock.json

 npm i express cors jsonwebtoken -S //保存到当前项目中

3.新建一个uitls文件夹,存放工具函数,在里面新建一个tokenUitls.js用来封装生成token和验证token的函数,在里面先引入JWT,然后再封装函数,并暴露出去

// 第一步:引入jwt
let jwt = require("jsonwebtoken");

// JWT的组成部分

// 1.Header(头)  作用:记录令牌类型、签名算法等 例如:{"alg":"HS256","type":"JWT"}

// 2.Payload(有效载荷) 作用:携带一些用户信息 例如{"userId":"1","username":"mingzi"}

// 3.Signature(签名) 作用:是对前两部分的签名,防止Token被篡改、确保安全性 例如 计算出来的签名,一个字符串

// 密钥---字符串
let privatekey = 'testjwt'; //自定义密钥
// 过期时间单位 s
// let time = 60*60;

// 第二步:封装生成token的函数 
function createToken(obj,exTime){
                        // obj代表有效载荷  privatekey代表密钥  expires过期时间 s
    let tempToken = jwt.sign(obj,privatekey,{expiresIn:exTime})
    // 把生成的token  return出去
    return tempToken
}

// 校验token的方法
function verifyToken(token){
    return new Promise((resolve,reject)=>{
        jwt.verify(token,privatekey,(err,data)=>{
            if(err){
                reject(err)
            }else{
                resolve(data)
            }
        })
    })
}

// 第三步:暴露出去
module.exports = {
    createToken,
    verifyToken
}

4.新建app.js搭建服务器

先写一个登录接口,如果验证用户名和密码没问题,就调用生成token的函数,发送给前台res.send({ massage:"登录成功",token})

let express = require("express");
let app = express();
// 第四步:引入封装的生成token的方法
let { createToken,verifyToken } = require("./utils/tokenUtils")
// 解决跨域
let cors = require("cors");
app.use(cors());
// 解析post请求
app.use(express.urlencoded({extended:false}))
app.use(express.json())

// 登录接口
app.post("/login",(req,res)=>{
    if(req.body.username!='xiaohao' || req.body.password!='123456'){
        res.send("用户名不匹配")
    }else{
        let token = createToken({username:req.body.username},1800)
        console.log('token',token);
        res.send({
            message:"登录成功",
            token
        })
    }
})

// 用中间件拦截请求
app.use((req,res,next)=>{
    // 获取前端传递过来的token
    // console.log(req.headers);
    let token = req.headers["authorization"];

    // 如果有token执行校验token操作
    if(token){
        verifyToken(token).then((rel => {
            // console.log(rel); //{ username: 'xiaohao', iat: 1667830826, exp: 1667832626 } 校验成功返回用户名,iat 发布时间,exp 到期时间
            if(rel.username){
                // 校验成功--中间件放行
                next();
            }
        }),err => {
            res.send("token过期,请重新登录" + err)
        })
    }else{
        // 如果没有token
        res.send("授权失败请先登录")
    }
})


// 获取信息的接口
app.get("/msg",(req,res)=>{
    res.send("其他信息")
})


app.listen(3000,() => {
    console.log("您的服务器以光速启动--->>>>>>");
}) 

5.前台发起ajax请求,先登录,调用接口生成token,并存储在localstorage中,后获取信息,把存储的token放在请求头中,调用接口后,执行验证token的函数,验证成功放行后面的接口。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
    <button>登录</button>
    <button>获取后台其他信息</button>
    <script>
        $('button').eq(0).click(function(){
            $.ajax({
                type:"POST",
                url:"http://localhost:3000/login",
                data:{
                    username:"xiaohao",
                    password:"123456"
                },

                success:function(data){
                    console.log('data',data);
                    // 客户端存储token
                    localStorage.setItem('token',data.token)
                },
                error:function(err){
                    console.log('err',err);
                }
            })
        })

        $('button').eq(1).click(function(){
            $.ajax({
                type:"get",
                url:"http://localhost:3000/msg",
                // 并在每次访问时加上这个token值。
                headers:{
                    // 翻译:授权;许可;权限的意思
                    Authorization:localStorage.getItem('token') || ''
                },
                success:function(data){
                    console.log('data',data);
                    localStorage.setItem('token',data.token)
                },
                error:function(err){
                    console.log('err',err);
                }
            })
        })
    </script>
</body>
</html>

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JWT(JSON Web Token)是一种用于身份验证的开放标准(RFC 7519)。它通过数字签名验证消息的完整性,因此,JWT可以安全地传输信息。JWT通常用于Web应用程序中,以验证用户的身份。 生成JWT token的步骤如下: 1. 首先,需要选择一个加密算法,如HMAC SHA256或RSA。 2. 构建JWT token的header部分。header部分是一个JSON对象,它描述了JWT的类型和加密算法。例如: ``` { "alg": "HS256", "typ": "JWT" } ``` 其中,"alg"表示使用的加密算法,"typ"表示JWT的类型。 3. 构建JWT token的payload部分。payload部分也是一个JSON对象,它包含要传输的信息,例如用户ID、用户名、过期时间等。例如: ``` { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } ``` 其中,"sub"表示主题(通常是用户ID),"name"表示用户名,"iat"表示JWT的发布时间。 4. 使用密钥对header部分和payload部分进行签名。签名可以确保消息的完整性和真实性。签名的方法取决于所选择的加密算法。例如,如果使用HMAC SHA256,签名可以如下计算: ``` HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) ``` 其中,"secret"是一个密钥,用于计算签名。 5. 将header部分、payload部分和签名组合在一起,用"点"连接起来,形成JWT token。例如: ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIy. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ``` 其中,第一个部分是base64UrlEncode后的header部分,第二个部分是base64UrlEncode后的payload部分,第三个部分是签名。 因为JWT token包含签名,所以接收方可以验证它的完整性和真实性。如果签名验证失败,说明该消息可能已被篡改或伪造。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值