JWT 登录认证:原理与 Flask 实现

JWT 登录认证:原理与 Flask 实现

前后端分离项目里,JWT(JSON Web Token)几乎是最常用的登录认证方案。这篇文章讲清楚它的原理,再给一版可以直接抄的 Flask 实现。

1. 为什么要用 JWT,而不是传统 Session

传统的 Session 认证依赖服务端存储会话信息(比如存在 Redis 或内存里),每次请求都要拿 Session ID 去查一次,服务端要维护状态,多台服务器之间还得做 Session 共享。

JWT 是一种无状态方案:服务端把用户信息签名后打包成一个 token 返回给客户端,之后客户端每次请求带上这个 token,服务端只需要验证签名,不用查任何存储。天然适合分布式、前后端分离的场景。

2. JWT 的结构

一个 JWT 由三部分组成,用 . 分隔:

header.payload.signature
  • header:声明算法类型,比如 HS256
  • payload:存放实际数据,比如用户 id、过期时间
  • signature:对前两部分用密钥签名,防止内容被篡改

注意:payload 只是 Base64 编码,不是加密,不要在里面塞密码这类敏感信息。

3. Flask 实现

安装依赖:

pip install pyjwt

生成 token:

import jwt
import datetime

SECRET_KEY = 'your-secret-key'  # 建议放到环境变量里

def generate_token(user_id):
payload = {
    'user_id': user_id,
    'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2),
    'iat': datetime.datetime.utcnow(),
}
return jwt.encode(payload, SECRET_KEY, algorithm='HS256')

登录接口里调用:

@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username')
password = request.json.get('password')
user = User.query.filter_by(username=username).first()
if not user or not user.check_password(password):
    return jsonify({'msg': '用户名或密码错误'}), 401
token = generate_token(user.user_id)
return jsonify({'token': token})

4. 用装饰器保护接口

写一个装饰器统一校验 token,避免每个接口都重复写验证逻辑:

from functools import wraps
from flask import request, jsonify, g

def login_required(f):
@wraps(f)
def decorated(*args, **kwargs):
    auth_header = request.headers.get('Authorization', '')
    if not auth_header.startswith('Bearer '):
        return jsonify({'msg': '缺少 token'}), 401
    token = auth_header.split(' ')[1]
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        g.user_id = payload['user_id']
    except jwt.ExpiredSignatureError:
        return jsonify({'msg': 'token 已过期'}), 401
    except jwt.InvalidTokenError:
        return jsonify({'msg': '无效的 token'}), 401
    return f(*args, **kwargs)
return decorated


@app.route('/profile')
@login_required
def profile():
user = User.query.get(g.user_id)
return jsonify(user.to_dict())

5. 常见的几个坑

  • token 过期时间设太长:一旦泄露,攻击者能用很久。一般 access token 设置成较短时间(比如几十分钟到几小时),配合 refresh token 做续期。
  • 退出登录做不了:JWT 本身是无状态的,服务端没法主动"作废"一个 token。如果要支持强制退出登录,通常需要引入黑名单机制(比如把已注销的 token 存进 Redis,验证时先查一下)。
  • payload 塞了敏感信息:payload 任何人都能 Base64 解码看到,不要放密码、手机号这类信息。

小结

JWT 的核心思路是"用签名代替服务端存储状态",天然适合前后端分离和分布式部署。用的时候记得控制好过期时间,需要强制下线功能的话再配合黑名单方案,基本就能覆盖大多数登录认证场景。

作者: yanleaf 发布时间: 2026-07-03 15:58:23 阅读数: 97 点赞数: 0 评论数:

评论区

备案期间,评论功能暂时关闭。