JWT Python
下面是简单的 生成 JWT Web Token 和 验证Token
import jwt
from jwt import exceptions
import time
SECRET_KEY = "!kLbMLtW4@lFnBlt"
# 创建JWT-Token
def create_token(name):
global SECRET_KEY
headers = {
"alg": "HS256",
"typ": "JWT"
}
exp = int(time.time() + 20)
print(exp)
payload = {
"iat": exp,
"login": name,
}
token = jwt.encode(payload=payload, key=SECRET_KEY, algorithm='HS256', headers=headers).decode('utf-8')
return token
## 验证JWT-Token
def validate_token(token):
global SECRET_KEY
payload = None
msg = None
try:
payload = jwt.decode(token, SECRET_KEY, True, algorithm='HS256')
except exceptions.ExpiredSignatureError:
msg = 'token expired'
except jwt.DecodeError:
msg = 'token fail'
except jwt.InvalidTokenError:
msg = 'invalidate token'
return (payload, msg)
if __name__ == '__main__':
token = create_token('admin')
validate_token(token)
当我们学会了如何制作token 和验证token 那么一切就简单了
1、第三系统生成token 且payload 带有身份信息以及时间戳
请求被登录的系统
2、被登录的系统提供入口 验证token的有效性以及时间范围有效性
然后就是本系统登录的事情了
以下是采用Odoo开源框架作为案例
Odoo JWT 核心代码
@http.route('/jwt/web/login', type='http', auth="none", csrf=False)
def jwt_login(self, **kw):
params = request.env['ir.config_parameter'].sudo()
jwt_token = kw.get('token')
redirect_url = kw.get('redirect_url', '/web')
if redirect_url != '/web':
redirect_url = base64.b64decode(redirect_url)
if not jwt_token:
_logger.error('缺少必要参数token')
return '缺少必要参数token'
# 获取 jwt token secret
jwt_secret = params.get_param('oauth_jwt_secret', '')
if not jwt_secret:
_logger.error('验证密钥未配置,请联系管理员')
return '验证密钥未配置,请联系管理员'
try:
data = jwt.decode(jwt_token, jwt_secret, algorithms='HS256')
except jwt.ExpiredSignatureError as e:
_logger.error(e)
return '身份认证已过期/%s' % e
except jwt.InvalidSignatureError as e:
_logger.error(e)
return '非法签名/%s' % e
except Exception as e:
_logger.info(e)
return '请求失败,请联系系统管理员'
# 验证 iat
errmsg = self._validate_iat(data)
if errmsg is not True:
return errmsg
login = data.get('login')
if login:
db = request.session.db
registry = registry_get(db)
with registry.cursor() as cr:
env = api.Environment(cr, SUPERUSER_ID, {
})
user_id = env['res.users'].sudo().search([('login', '=', login)], limit=1)
if user_id:
# 采用jwt_token作为临时密码进行登录验证
user_id.oauth_access_token = jwt_token
env.cr.commit()
uid = request.session.authenticate(request.session.db, login, jwt_token)
# 登录成功之后清除token密码 保证不破坏原有机制
user_id.oauth_access_token = None
env.cr.commit()
if uid:
request.params['login_success'] = True
return http.redirect_with_hash(redirect_url)
error_msg = '当前用户身份信息有误'
return error_msg
def _validate_iat(self, payload):
"""
验证 时间戳
:param payload:
:return:
"""
if 'iat' not in payload.keys():
errmsg = 'JWT payload中缺少iat参数'
return errmsg
if 'exp' not in payload.keys():
# 默认2小时
now_stamp = time.time()
if now_stamp > int(payload.get('iat')) + 7200:
errmsg = 'Token签名已失效'
return errmsg
return True