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 实现 安装依赖: ```bash pip install pyjwt ``` 生成 token: ```python 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') ``` 登录接口里调用: ```python @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,避免每个接口都重复写验证逻辑: ```python 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 阅读数: 1 点赞数: 0 评论数:

评论区

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