使用Flask和JWT进行用户身份认证

绮梦之旅 2022-10-18 ⋅ 23 阅读

在Web应用程序中,用户身份认证是一个非常重要且常见的功能。它确保只有授权的用户才能访问特定的资源和操作。在本篇博客中,将介绍如何使用Flask和JWT(JSON Web Token)进行用户身份认证。

什么是JWT?

JWT是一种用于身份验证和授权的安全传输的数据结构。它是一个加密签名的字符串,由三个部分组成:头、载荷和签名。头部包含加密算法和类型信息,载荷中包含身份验证的相关信息,签名用于验证数据的完整性和真实性。

JWT的一个巨大优势是它的无状态性,即服务器不需要在后端存储数据。这使得JWT成为构建可扩展和分布式应用程序的理想工具。

准备工作

在开始之前,确保已经在系统中安装了Python、Flask和PyJWT。可以使用以下命令安装它们:

$ pip install flask
$ pip install pyjwt

项目搭建

首先,创建一个名为app.py的新文件,并在其中导入所需的模块:

from flask import Flask
from flask_jwt import JWT
from flask import jsonify
from werkzeug.security import safe_str_cmp

然后,初始化一个Flask应用程序:

app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret'  # 用于JWT的签名密钥

接下来,定义一个用户类来模拟数据库中的用户记录:

class User:
    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = password

users = [
    User(1, 'user1', 'password1'),
    User(2, 'user2', 'password2')
]

然后,创建一个身份验证函数,用于验证用户的用户名和密码是否正确:

def authenticate(username, password):
    for user in users:
        if user.username == username and user.password == password:
            return user

def identity(payload):
    user_id = payload['identity']
    for user in users:
        if user.id == user_id:
            return user

接下来,将authenticateidentity函数传递给JWT对象来进行身份验证和授权:

jwt = JWT(app, authenticate, identity)

现在,可以编写几个路由来测试身份认证的功能。在路由中,使用@jwt_required()装饰器来保护需要身份认证的资源:

@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')
    
    user = authenticate(username, password)
    
    if user:
        token = jwt.jwt_encode_callback(user)
        return jsonify({'token': token})
    else:
        return jsonify({'error': 'Invalid credentials'}), 401

@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
    return jsonify({'message': 'You are accessing protected resource'})

测试身份认证

现在,即可以使用任意的HTTP客户端来测试身份认证功能。首先,确保Flask应用程序已经启动。然后,发送一个POST请求到/login

$ curl --header "Content-Type: application/json" \
       --request POST \
       --data '{"username":"user1","password":"password1"}' \
       http://localhost:5000/login

将会得到一个包含JWT的响应:

{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSIsImlhdCI6MTYyMzczODQyOCwiZXhwIjoxNjIzNzQyMDI4fQ.FifPOuMyIiLfrO_im_Aa6OTWcBotKJ7KZIoljHa26Ns"}

使用这个JWT令牌,在请求中包含Authorization头来访问受保护的资源:

$ curl --header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSIsImlhdCI6MTYyMzczODQyOCwiZXhwIjoxNjIzNzQyMDI4fQ.FifPOuMyIiLfrO_im_Aa6OTWcBotKJ7KZIoljHa26Ns" \
       http://localhost:5000/protected

将会得到一个包含"message"的响应:

{"message":"You are accessing protected resource"}

如果不使用JWT令牌,或者提供的令牌无效或已过期,则会收到401错误。

结论

本篇博客中,介绍了如何使用Flask和JWT进行用户身份认证。通过创建一个Flask应用程序,定义用户类和相关的身份认证函数,以及使用JWT对象来保护需要身份认证的资源,可以实现简单而强大的用户身份认证功能。这对于构建安全的Web应用程序来说非常重要,因为只有经过身份验证和授权的用户才能访问受保护的资源。


全部评论: 0

    我有话说: