面试题答案
一键面试设计思路
- 统一JWT格式:定义一个基础的JWT载荷格式,包含通用信息,如用户ID、用户名等,各系统在此基础上可扩展自定义字段。
- 单点登录(SSO)服务:搭建一个SSO服务,负责用户登录认证,生成通用的JWT令牌。用户在任意一个系统登录,实际是与SSO服务交互。
- 系统间信任机制:各后端服务系统需信任SSO服务生成的JWT。可通过配置SSO服务的公钥来验证JWT签名。
- JWT验证中间件:在每个后端服务系统中创建JWT验证中间件,拦截请求,验证JWT的有效性,包括签名验证、过期时间验证等。
关键代码实现(以Python Flask和PyJWT库为例)
- SSO服务生成JWT:
import jwt
from flask import Flask, request, jsonify
from datetime import datetime, timedelta
app = Flask(__name__)
SECRET_KEY = 'your_secret_key'
EXPIRATION_TIME = timedelta(minutes = 30)
@app.route('/login', methods=['POST'])
def login():
data = request.get_json()
username = data.get('username')
password = data.get('password')
# 模拟用户验证
if username == 'test' and password == 'test':
payload = {
'user_id': 1,
'username': username,
'exp': datetime.utcnow() + EXPIRATION_TIME
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
return jsonify({'token': token}), 200
return jsonify({'message': 'Invalid credentials'}), 401
if __name__ == '__main__':
app.run(debug=True)
- 后端服务系统JWT验证中间件:
import jwt
from flask import Flask, request, jsonify, g
from functools import wraps
app = Flask(__name__)
SECRET_KEY = 'your_secret_key'
def jwt_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = None
if 'x-access-token' in request.headers:
token = request.headers['x-access-token']
if not token:
return jsonify({'message': 'Token is missing'}), 401
try:
data = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
g.user_id = data['user_id']
g.username = data['username']
except jwt.ExpiredSignatureError:
return jsonify({'message': 'Token has expired'}), 401
except jwt.InvalidTokenError:
return jsonify({'message': 'Invalid token'}), 401
return f(*args, **kwargs)
return decorated
@app.route('/protected', methods=['GET'])
@jwt_required
def protected():
return jsonify({'message': 'This is a protected route', 'user_id': g.user_id, 'username': g.username}), 200
if __name__ == '__main__':
app.run(debug=True)
以上代码实现了一个简单的SSO服务生成JWT以及后端服务系统验证JWT的机制,实际应用中需根据具体需求完善和优化,如用户存储、加密算法选择等。