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

JWT学习:从入门到实践的全面指南

标签:
安全 API
概述

JWT学习是一个全面的指南,涵盖了JWT的基本概念、工作原理及其组成部分。本文详细介绍了JWT在用户认证、信息交换和API访问控制等场景中的应用,并提供了JWT创建、解码和验证的基础操作示例。

JWT学习:从入门到实践的全面指南
1. JWT简介

1.1 什么是JWT

JWT(JSON Web Token)是一种开放的标准(RFC 7519),用于在网络应用环境间安全地将信息从客户端传递到服务器端。JWT基于一种紧凑、自包含的、可传递的格式,通常用于身份验证(登录)、信息交换或访问控制等场景。

1.2 JWT的工作原理

JWT的工作原理可以概括为以下三个步骤:

  1. 生成JWT:服务器生成一个安全的token,包括头信息和载荷,然后用密钥签名。
  2. 传递JWT:客户端接收JWT,并将其保存在本地。通常保存在浏览器的localStorage中或者sessionStorage中,或者是作为HTTP请求的头信息传递。
  3. 验证JWT:每次客户端向服务器发送请求时,都需要携带JWT。服务器收到请求后,会验证这个JWT是否有效。这包括检查签名是否正确以及载荷是否有效。

以下是JWT生成、传递及验证的代码示例:

JWT生成示例

const jwt = require('jsonwebtoken');
const secret = 'yourSecretKey';

// 生成JWT
const token = jwt.sign(
  {
    user: 'John Doe',
    id: 12345
  },
  secret,
  {
    expiresIn: '1h'
  }
);

console.log(token);

JWT验证示例

const jwt = require('jsonwebtoken');
const token = 'yourTokenString';

// 验证JWT
jwt.verify(token, secret, (err, decoded) => {
  if (err) {
    console.log('Invalid token');
  } else {
    console.log('Token is valid', decoded);
  }
});

1.3 JWT的三个部分介绍

JWT由三部分组成,中间由“.”分隔:

  1. Header(头部):包含令牌的类型(总是为JWT)和所使用的签名算法(例如HMAC SHA256RSA),通常由base64编码。

    示例代码:

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

    经过base64编码后的结果为:

    eyJsYWciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9
  2. Payload(载荷):载荷可以用来存放声明,JWT的标准声明可参考JWT标准文档。载荷部分也经过了base64编码。例如,载荷可以包含用户的身份信息,如用户ID、用户名、过期时间等。

    示例代码:

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

    经过base64编码后的结果为:

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
  3. Signature(签名):签名确保了JWT的完整性和真实性。它使用头部中指定的算法,通过特定密钥签名载荷部分。签名也经过了base64编码。

    示例代码:

    HMACSHA256(
     base64UrlEncode(header) + "." +
     base64UrlEncode(payload),
     secret)

    例如,如果使用HS256算法,签名如下:

    eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ==.dGJjZmJjZmI=
2. JWT应用场景

2.1 用户认证

JWT非常适合用于用户认证。认证时,服务器验证JWT的签名,并将JWT附加到返回的响应中,客户端则在后续的请求中将JWT作为认证信息包含在请求头中,这样可以减少数据库查询次数,提高系统性能和安全性。

JWT用户认证示例

const jwt = require('jsonwebtoken');
const secret = 'yourSecretKey';

app.post('/login', (req, res) => {
  const user = req.body; // 假设这里是从数据库获取的用户信息
  const token = jwt.sign(user, secret, { expiresIn: '1h' });
  res.json({ token });
});

app.use((req, res, next) => {
  const token = req.headers['authorization'];
  if (token) {
    jwt.verify(token, secret, (err, decoded) => {
      if (err) {
        res.status(403).json({ message: 'Invalid token' });
      } else {
        req.decoded = decoded;
        next();
      }
    });
  } else {
    res.status(403).json({ message: 'No token provided' });
  }
});

app.get('/protected', (req, res) => {
  res.json({ message: 'Protected content', user: req.decoded });
});

2.2 信息交换

JWT可以用来安全交换信息。例如,一个API可以将用户信息作为JWT发送给另一个API,接收方可以验证JWT并了解发送方的身份和信息。

JWT信息交换示例

const jwt = require('jsonwebtoken');
const secret = 'yourSecretKey';

// 发送JWT
const token = jwt.sign(
  {
    user: 'John Doe',
    id: 12345
  },
  secret,
  {
    expiresIn: '1h'
  }
);

// 接收和验证JWT
jwt.verify(token, secret, (err, decoded) => {
  if (err) {
    console.log('Invalid token');
  } else {
    console.log('Token is valid', decoded);
  }
});

2.3 API访问控制

JWT也可以用于API访问控制。通过验证JWT,服务器可以确定请求方是否有权限访问特定资源或执行特定操作。

JWT API访问控制示例

const jwt = require('jsonwebtoken');
const secret = 'yourSecretKey';

app.get('/api/resource', (req, res) => {
  const token = req.headers['authorization'];
  if (token) {
    jwt.verify(token, secret, (err, decoded) => {
      if (err) {
        res.status(403).json({ message: 'Invalid token' });
      } else {
        res.json({ message: 'Access granted', user: decoded });
      }
    });
  } else {
    res.status(403).json({ message: 'No token provided' });
  }
});
3. JWT基础操作

3.1 创建JWT

创建JWT包括生成头部、载荷然后签名。例如,使用Node.js创建JWT,可以使用jsonwebtoken库。

const jwt = require('jsonwebtoken');

const token = jwt.sign(
  {
    user: 'John Doe',
    id: 12345
  },
  'secret',
  {
    expiresIn: '1h'
  }
);

console.log(token);

3.2 解码JWT

解码JWT不需要验证其签名,只需要将JWT字符串拆分成头部、载荷和签名三部分,然后使用base64解码头部和载荷部分。

示例代码:

const jwt = require('jsonwebtoken');
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxhPQpJ4dGOWD3YoKwFf0C1Z4CpSb4KZx168DR4';

const decoded = jwt.decode(token, { complete: true });
console.log(decoded);

3.3 验证JWT

验证JWT涉及检查签名是否正确以及过期时间等。例如,使用Node.js验证JWT。

示例代码:

const jwt = require('jsonwebtoken');

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxhPQpJ4dGOWD3YoKwFf0C1Z4CpSb4KZx168DR4';

try {
  const decoded = jwt.verify(token, 'secret');
  console.log('Token is valid', decoded);
} catch (error) {
  console.log('Token is not valid', error);
}
4. 使用JWT的注意事项

4.1 签名算法选择

选择合适的安全算法对于JWT的安全性至关重要。最常用的算法包括HS256(使用共享密钥的HMAC算法)和RS256(使用公钥和私钥的RSA算法)。选择算法时要考虑到安全性和复杂性。

4.2 令牌过期策略

设定合理的过期时间可以限制JWT的有效期,减少JWT被滥用的风险。过期时间可以设置为5分钟1小时或更长,具体取决于应用需求。

4.3 令牌刷新机制

为了避免用户频繁重新登录,可以实现JWT的刷新机制。例如,可以在JWT过期前发起刷新请求,服务器返回新的JWT。

5. 实战演练

5.1 使用Node.js实现JWT认证

以一个简单的Node.js应用程序为例,演示如何使用JWT进行用户认证。首先安装必要的库:

npm install express jsonwebtoken

示例代码:

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

const secret = 'yoursecret';

app.post('/login', (req, res) => {
  const user = req.body; // 假设这里是从数据库获取的用户信息
  const token = jwt.sign(user, secret, { expiresIn: '1h' });
  res.json({ token });
});

app.use((req, res, next) => {
  const token = req.headers['authorization'];
  if (token) {
    jwt.verify(token, secret, (err, decoded) => {
      if (err) {
        res.status(403).json({ message: 'Invalid token' });
      } else {
        req.decoded = decoded;
        next();
      }
    });
  } else {
    res.status(403).json({ message: 'No token provided' });
  }
});

app.get('/protected', (req, res) => {
  res.json({ message: 'Protected content', user: req.decoded });
});

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

5.2 使用Python实现JWT认证

以一个简单的Python Flask应用程序为例,演示如何使用JWT进行用户认证。首先安装必要的库:

pip install Flask
pip install Flask-JWT-Extended

示例代码:

from flask import Flask, request, jsonify
from flask_jwt_extended import JWTManager, jwt_required, create_access_token

app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'yoursecret'
jwt = JWTManager(app)

@app.route('/login', methods=['POST'])
def login():
    user = request.json.get('user', None)
    if user:
        token = create_access_token(identity=user, expires_delta=False)
        return jsonify(token=token)
    return jsonify({'msg': 'Missing user parameter'}), 400

@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
    return jsonify({'msg': 'Access protected content', 'user': get_jwt_identity()})

if __name__ == '__main__':
    app.run()
6. 常见问题解答

6.1 JWT安全性如何保证

JWT的安全性依赖于签名算法和密钥的安全性。密钥应该保密,只有服务器知道。JWT应通过HTTPS传输,以防止中间人攻击。同时,确保载荷中的数据不包含敏感信息。

6.2 如何处理过期的JWT

过期的JWT可以使用刷新机制来处理。当JWT即将过期时,客户端可以发起刷新请求,服务器验证身份后返回新的JWT。

6.3 JWT与Cookie的区别

  • 存储:JWT存储在前端,可以存储在本地存储或HTTP头中;Cookie存储在服务器端,由浏览器自动管理。
  • 安全性:JWT不依赖于服务器状态,可以通过HTTPS传输保证安全;Cookie在未加密的HTTP连接中容易被窃取。
  • 跨域:JWT可以在任何站点间传递,而Cookie只能传递到同源站点。
  • 大小限制:JWT的大小限制较小,适合存储少量信息;Cookie的大小限制较大,可以存储更多数据。

JWT适用于不需要服务器状态保持的场景,而Cookie适合需要服务器状态保持的场景。

点击查看更多内容
TA 点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消