为了账号安全,请及时绑定邮箱和手机立即绑定

JWT入门:轻松掌握JSON Web Tokens基础知识

标签:
杂七杂八
概述

JWT入门介绍了一种紧凑且自包含的网络应用信息传输标准,广泛应用于身份验证和信息交换。文章详细讲解了JWT的工作原理、组成部分及其优势,并提供了生成和验证JWT的示例代码。JWT在用户认证和API保护中的应用也得到了充分展示,帮助读者理解其在实际开发中的重要性。

JWT简介

什么是JWT

JSON Web Token (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且自包含的方式,用于在网络应用间安全地将信息作为JSON对象传输。JWT通常用于身份验证和信息交换,广泛应用于Web、移动应用以及前后端通信中。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。

JWT的工作原理

JWT的工作原理基于三个部分:

  1. 头部(Header):包含声明类型(type)和签名算法(algorithm)。例如,HMAC SHA256、RS256等。
  2. 载荷(Payload):包含声明(claims)。这些声明可以分为三大类:
    • 注册声明(Registered Claims):如iss(发布者)、exp(过期时间)、sub(主申明)、aud(受众)等。
    • 公共声明(Public Claims):不是JWT规范定义的,但可以在所有应用中定义以及使用。
    • 私有声明(Private Claims):由某个应用自定义的声明。
  3. 签名(Signature):在头部和载荷经过编码后与一个秘钥(密钥/私钥/公钥)一起生成签名。该签名经过了相应的加密算法(如HMAC SHA256或RSA)生成,用于验证消息的完整性和签名者的身份。

JWT的优势和应用场景

JWT的主要优势包括:

  • 紧凑性:JWT作为一个URL安全的Token,非常适合作为HTTP请求的Authorization头信息。
  • 无状态:服务器无需保存Session数据,减轻了服务器端的存储负担。
  • 安全性:通过HMAC、RSA等加密算法确保了消息的完整性和签名者的身份。
  • 跨语言支持:几乎所有的编程语言都支持JWT,方便跨平台跨语言的应用开发。
  • 自包含性:JWT包含了所有必要的信息,使得接收方可以根据这些信息验证Token的来源和内容。

JWT广泛应用于以下场景:

  • 用户认证:利用JWT实现用户登录,生成Token并让客户端使用Token进行后续请求。
  • 信息交换:前后端之间的信息传递,如用户数据传输等。
  • 权限控制:基于JWT中的Claim来决定用户权限。
  • API安全控制:在API接口中使用JWT确保只有被授权的用户才能访问资源。
JWT结构

JWT的组成部分

JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。每个部分都是一个单独的JSON对象,然后被Base64编码。

头部(Header)

头部包含两部分信息:

  1. 声明类型(type):通常是JWT
  2. 签名算法(algorithm):例如,HMAC SHA256、RS256等。

例如:

{
  "typ": "JWT",
  "alg": "HS256"
}

载荷(Payload)

载荷包含声明(claims)。这些声明可以分为:

  • 注册声明(Registered Claims):如iss(发布者)、exp(过期时间)、sub(主申明)、aud(受众)等。
  • 公共声明(Public Claims):不是JWT规范定义的,但可以在所有应用中定义以及使用。
  • 私有声明(Private Claims):由某个应用自定义的声明。

例如:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

签名(Signature)

签名通过对头部和载荷的Base64编码后的字符串,再与一个秘钥(密钥/私钥/公钥)一起生成签名。该签名经过了相应的加密算法(如HMAC SHA256或RSA)生成,用于验证消息的完整性和签名者的身份。

每个部分的作用详解

  • 头部(Header):定义了Token的类型和签名算法。
  • 载荷(Payload):包含了Token的有效信息。
  • 签名(Signature):通过加密算法,保证了Token的完整性和来源的可信性。
如何生成JWT

使用Python生成JWT

Python可以通过pyjwt库生成JWT。首先需要安装库:

pip install pyjwt

以下是一个简单的示例代码,生成JWT:

import jwt
import datetime

# 密钥
secret_key = 'my_secret_key'

# 载荷
payload = {
    'sub': '1234567890',
    'name': 'John Doe',
    'iat': datetime.datetime.utcnow(),
    'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=30)
}

# 生成JWT
token = jwt.encode(payload, secret_key, algorithm='HS256')
print(token)

使用JavaScript生成JWT

JavaScript可以通过jsonwebtoken库生成JWT。首先需要安装库:

npm install jsonwebtoken

以下是一个简单的示例代码,生成JWT:

const jwt = require('jsonwebtoken');

// 密钥
const secret_key = 'my_secret_key';

// 载荷
const payload = {
    sub: '1234567890',
    name: 'John Doe',
    iat: new Date().getTime() / 1000,
    exp: new Date().getTime() / 1000 + 30
};

// 生成JWT
const token = jwt.sign(payload, secret_key, { algorithm: 'HS256' });
console.log(token);
如何验证和解码JWT

使用在线工具解码JWT

在线工具如 jwt.io 可以帮助你解码JWT。输入JWT Token后,点击Decode按钮,即可看到头部、载荷以及签名部分的信息。

使用编程语言验证JWT的有效性

使用Python验证JWT

Python可以通过pyjwt库验证JWT的有效性:

import jwt

# 密钥
secret_key = 'my_secret_key'

# JWT Token
token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxhPQOak8vI2IoO4h6XxW6MwMxt9HR5JcmuE1Ls'

try:
    # 验证JWT的有效性
    decoded = jwt.decode(token, secret_key, algorithms=['HS256'])
    print("JWT验证通过:", decoded)
except jwt.ExpiredSignatureError:
    print("JWT已过期")
except jwt.InvalidTokenError:
    print("JWT无效")

使用JavaScript验证JWT

JavaScript可以通过jsonwebtoken库验证JWT的有效性:

const jwt = require('jsonwebtoken');

// 密钥
const secret_key = 'my_secret_key';

// JWT Token
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxhPQOak8vI2IoO4h6XxW6MwMxt9HR5JcmuE1Ls';

try {
    // 验证JWT的有效性
    const decoded = jwt.verify(token, secret_key);
    console.log("JWT验证通过:", decoded);
} catch (error) {
    console.log("JWT验证失败:", error);
}
JWT安全性常见问题

JWT的签名算法

JWT的签名算法包括:

  • HMAC SHA256:使用密钥的哈希算法,适合于同一域名下的应用。
  • RS256:使用公钥和私钥的非对称加密算法,适合于跨域名的应用。

如何防止JWT被篡改

为了防止JWT被篡改,需要确保:

  1. 使用安全的签名算法:如HMAC SHA256或RS256。
  2. 设置过期时间:过期时间可以限制Token的有效期。
  3. 使用安全的环境:避免在不安全的环境中存储和传输JWT。

JWT存储与传输的安全性

JWT存储和传输的安全性需要:

  1. HTTPS传输:使用HTTPS确保传输的安全性。
  2. 存储在Session中:避免在客户端直接存储JWT,应存储在Session中。
  3. 不使用Cookie:避免使用Cookie存储JWT,因为Cookie更容易受到CSRF攻击。
实战案例

使用JWT实现用户认证

用户认证是JWT最常见的应用场景之一。以下是一个简单的示例,展示如何使用JWT实现用户认证。

示例代码

这里使用Node.js和Express进行演示:

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

const secret_key = 'my_secret_key';

app.post('/login', (req, res) => {
    const user = req.body; // 假设请求体里面有用户名和密码,这里进行简单的检查
    if (user.username === 'admin' && user.password === 'password') {
        const token = jwt.sign({ username: user.username }, secret_key, {
            expiresIn: '1h'
        });
        res.status = 200;
        res.json({ token });
    } else {
        res.status = 401;
        res.json({ message: 'Unauthorized' });
    }
});

app.get('/protected', (req, res) => {
    const token = req.headers.authorization.split(' ')[1];
    if (token) {
        jwt.verify(token, secret_key, (err, decoded) => {
            if (err) {
                res.status = 403;
                res.json({ message: 'Forbidden' });
            } else {
                res.status = 200;
                res.json({ message: 'Authorized', user: decoded.username });
            }
        });
    } else {
        res.status = 401;
        res.json({ message: 'Unauthorized' });
    }
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

在这个示例中,用户登录时会返回一个JWT Token。该Token在访问受保护的路由时需要携带,并且会通过验证来确认用户身份。

JWT在API中的应用

JWT广泛应用于API开发中,用于身份验证和权限控制。以下是一个示例,展示如何在API中使用JWT进行认证和权限控制。

示例代码

这里使用Node.js和Express进行演示:

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

const secret_key = 'my_secret_key';

app.post('/login', (req, res) => {
    const user = req.body; // 假设请求体里面有用户名和密码,这里进行简单的检查
    if (user.username === 'admin' && user.password === 'password') {
        const token = jwt.sign({ username: user.username }, secret_key, {
            expiresIn: '1h'
        });
        res.status = 200;
        res.json({ token });
    } else {
        res.status = 401;
        res.json({ message: 'Unauthorized' });
    }
});

app.get('/api/users', (req, res) => {
    const token = req.headers.authorization.split(' ')[1];
    if (token) {
        jwt.verify(token, secret_key, (err, decoded) => {
            if (err) {
                res.status = 403;
                res.json({ message: 'Forbidden' });
            } else {
                res.status = 200;
                res.json({ message: 'Authorized', user: decoded.username });
            }
        });
    } else {
        res.status = 401;
        res.json({ message: 'Unauthorized' });
    }
});

app.get('/api/users/:userId', (req, res) => {
    const token = req.headers.authorization.split(' ')[1];
    if (token) {
        jwt.verify(token, secret_key, (err, decoded) => {
            if (err) {
                res.status = 403;
                res.json({ message: 'Forbidden' });
            } else {
                const userId = req.params.userId;
                // 假设用户ID和Token中的用户匹配
                if (decoded.username === userId) {
                    res.status = 200;
                    res.json({ message: 'Authorized', user: decoded.username });
                } else {
                    res.status = 403;
                    res.json({ message: 'Forbidden' });
                }
            }
        });
    } else {
        res.status = 401;
        res.json({ message: 'Unauthorized' });
    }
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

在这个示例中,用户登录时会返回一个JWT Token。该Token在访问受保护的API端点时需要携带,并且会通过验证来确认用户身份。此外,对于特定用户资源的访问,还需要验证Token中的用户ID是否与请求的用户ID匹配。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消