本文详细介绍了JWT的工作机制和单点登录(SSO)的概念,解释了JWT如何支持用户在多个系统中使用同一Token进行身份验证,简化了用户的登录流程,提高了系统的安全性和可维护性。
JSON Web Token (JWT) 是一种开放标准 (RFC 7519),用于在网络通信中传输安全声明。JWT 的设计目的是为了在网络应用环境之间传递声明,可以通过它来实现用户身份认证和授权。JWT 由三个部分组成:
JWT 的结构如下:
<Header>.<Payload>.<Signature>
单点登录(Single Sign-On, SSO)是指用户只需登录一次,即可访问多个关联系统或服务,而不需要重复登录的过程。这种方法提高了用户体验,同时减少了密码管理的复杂性。
JWT 可以作为 Token 被用于 SSO 实现,通过生成一个全局有效的 JWT,用户可以在多个系统中使用同一个 Token 进行身份验证。这种方式不仅简化了用户的登录过程,还提高了系统的安全性和可维护性。
优点:
缺点:
jjwt
,Python 中的 PyJWT
。示例代码:安装 Python 依赖
pip install pyjwt
生成 JWT:
import jwt import datetime def create_jwt_token(user_id, secret_key): payload = { 'user_id': user_id, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30) # 设置过期时间 } token = jwt.encode(payload, secret_key, algorithm='HS256') return token # 实例 user_id = 1 secret_key = 'supersecret' token = create_jwt_token(user_id, secret_key) print(token)
验证 JWT:
def verify_jwt_token(token, secret_key): try: payload = jwt.decode(token, secret_key, algorithms=['HS256']) return payload except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None # 实例 token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE2NjI5ODg1MjJ9.dU89g8w82f9d29f92d92f92d92d92d92f9' verified_payload = verify_jwt_token(token, secret_key) print(verified_payload)
用户登录逻辑:
def user_login(username, password): # 这里应该进行数据库查询验证用户名和密码 if username == 'admin' and password == 'password': user_id = 1 token = create_jwt_token(user_id, secret_key) return token return None # 实例 username = 'admin' password = 'password' token = user_login(username, password) print(token)
存储 JWT:
import http.cookies as Cookie def store_jwt_token(token): cookie = Cookie.SimpleCookie() cookie['jwt'] = token cookie['jwt']['expires'] = 3600 # 设置Cookie过期时间 return cookie # 实例 cookie = store_jwt_token(token) print(cookie)
发送 JWT:
import requests def send_jwt_request(url, token): headers = {'Authorization': f'Bearer {token}'} response = requests.get(url, headers=headers) return response # 实例 url = 'https://example.com/api/resource' response = send_jwt_request(url, token) print(response.text)
我们选择 Python 语言进行实现。假设已经搭建好开发环境,安装必要的依赖。
创建项目结构:
app.py
:主应用逻辑models.py
:数据库模型auth.py
:身份验证逻辑config.py
:配置文件编写模型文件:
# models.py class User: def __init__(self, id, username, password): self.id = id self.username = username self.password = password
实现身份验证逻辑:
# auth.py import jwt import datetime def create_jwt_token(user_id, secret_key): payload = { 'user_id': user_id, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30) } token = jwt.encode(payload, secret_key, algorithm='HS256') return token def verify_jwt_token(token, secret_key): try: payload = jwt.decode(token, secret_key, algorithms=['HS256']) return payload except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None
主应用逻辑:
# app.py from flask import Flask, request, jsonify from models import User from auth import create_jwt_token, verify_jwt_token import config app = Flask(__name__) # 模拟用户数据 users = [ User(1, 'admin', 'password') ] @app.route('/login', methods=['POST']) def login(): username = request.json.get('username') password = request.json.get('password') user = next((u for u in users if u.username == username and u.password == password), None) if user: token = create_jwt_token(user.id, config.SECRET_KEY) return jsonify({'token': token}) return jsonify({'error': 'Invalid credentials'}), 401 @app.route('/protected') def protected(): token = request.headers.get('Authorization', None) if token: token = token.replace('Bearer ', '', 1) payload = verify_jwt_token(token, config.SECRET_KEY) if payload: return jsonify({'user_id': payload['user_id']}) return jsonify({'error': 'Invalid token'}), 401 if __name__ == '__main__': app.run(port=5000)
# config.py SECRET_KEY = 'supersecretkey'
示例代码:
import logging logging.basicConfig(level=logging.DEBUG) @app.route('/login', methods=['POST']) def login(): try: username = request.json.get('username') password = request.json.get('password') logging.debug(f'Received login request for {username}') user = next((u for u in users if u.username == username and u.password == password), None) if user: token = create_jwt_token(user.id, config.SECRET_KEY) logging.debug(f'Generated JWT token for {username}') return jsonify({'token': token}) return jsonify({'error': 'Invalid credentials'}), 401 except Exception as e: logging.error(f'Exception during login: {str(e)}') return jsonify({'error': 'Internal server error'}), 500