使用JSON Web Tokens进行身份验证

编程艺术家 2021-04-06 ⋅ 19 阅读

身份验证是在 Web 应用程序中一项重要的安全功能。它用于确定用户的身份,并授权其访问特定的资源或功能。JSON Web Tokens(JWT)是一种流行的身份验证机制,它可以安全地在客户端和服务器之间传递身份验证信息。

什么是 JSON Web Tokens?

JSON Web Tokens(JWT)是一种开放的标准(RFC 7519),用于在客户端和服务器之间传递可验证的声明。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。

头部

头部通常由算法和令牌类型组成,用于指示签名所用的算法和令牌的类型(比如 JWT)。

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

载荷

载荷包含了有关用户和其他声明的信息。它可以包括标准的声明(比如用户名、邮箱地址)以及自定义的声明。载荷是可编码的,但并不加密,因此不应该包含敏感的信息。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

签名

签名用于验证消息的完整性,并确保发送者是可信的。在服务器端使用头部和载荷组成的字符串与服务器密钥进行加密生成签名,客户端使用相同的密钥进行验证。

身份验证流程

使用 JWT 进行身份验证的流程如下:

  1. 用户通过提供用户名和密码进行身份验证。
  2. 服务器验证用户提供的凭据。
  3. 如果凭据有效,服务器生成一个 JWT 并返回给客户端。
  4. 客户端在每个后续请求中将 JWT 作为 Authorization 头部的一部分发送给服务器。
  5. 服务器验证 JWT 的有效性,并根据其中的声明授权访问。

代码示例

服务器端

import jwt
from datetime import datetime, timedelta
from flask import Flask, request, jsonify

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

def generate_token(user_id):
    payload = {
        'sub': user_id,
        'exp': datetime.utcnow() + timedelta(minutes=30)
    }
    token = jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')
    return token

def validate_token(token):
    try:
        payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
        return payload['sub']
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')
    
    # 验证用户名和密码
    if username == 'admin' and password == 'admin123':
        # 生成 JWT
        token = generate_token(1)
        return jsonify({'token': token})
    else:
        return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/protected', methods=['GET'])
def protected():
    auth_header = request.headers.get('Authorization')
    if auth_header:
        token = auth_header.split(' ')[1]
        user_id = validate_token(token)
        if user_id:
            return jsonify({'message': 'Welcome user {}!'.format(user_id)})
    
    return jsonify({'error': 'Unauthorized'}), 401

if __name__ == '__main__':
    app.run()

客户端

function login() {
    const username = document.getElementById('username').value;
    const password = document.getElementById('password').value;
    
    fetch('/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({username, password})
    }).then(response => response.json())
      .then(data => {
          if (data.token) {
              localStorage.setItem('token', data.token);
              // 登录成功后跳转到受保护的页面
              window.location.href = '/protected';
          } else {
              alert(data.error);
          }
      });
}

function loadProtectedPage() {
    const token = localStorage.getItem('token');
    
    fetch('/protected', {
        headers: {
            'Authorization': `Bearer ${token}`
        }
    }).then(response => response.json())
      .then(data => {
          if (data.message) {
              document.getElementById('content').innerText = data.message;
          } else {
              alert(data.error);
              // 如果没有授权则跳转到登录页面
              window.location.href = '/login.html';
          }
      });
}

总结

使用 JSON Web Tokens 进行身份验证可以提供简单而安全的解决方案。它可以在客户端和服务器之间传递可验证的声明,并免去了使用会话和 cookies 的繁琐过程。然而,仍然需要在服务器端进行适当的验证和授权,以确保数据的安全性和完整性。


全部评论: 0

    我有话说: