import time
import datetime
from aiohttp import web
from functools import wraps
import jwt
class Authorization():
"""admin jwt的解析和生成"""
def __init__(self, request):
self.request = request
self.relative_path = request.raw_path
self.db = self.request.app['db']
self.days = 7
# 创建token
def _generate_tokens(self, id, permission,with_refresh_token=True, **kwargs):
now = datetime.datetime.utcnow()
expiry = now + datetime.timedelta(hours=self.request.app['JWT_EXPIRY_HOURS'])
store_data = {'id': id, "permission": permission, "duration": kwargs.get('duration'), 'refresh':True},refresh_expiry}
store_data.update(kwargs)
token = self.generate_jwt(store_data, expiry)
refresh_token = None
if with_refresh_token:
refresh_expiry = now + datetime.timedelta(days=self.days)
refresh_token = self.generate_jwt(
{'id': id, "permission": permission, "duration": kwargs.get('duration'), 'refresh': True}, refresh_expiry)
return token, refresh_token
async def put_token(self, id, permission, is_refresh_token, **kwargs):
"""更新token"""
if id and is_refresh_token:
token, refresh_token = self._generate_tokens(id, int(permission), duration=kwargs.get('duration'), with_refresh_token=True)
# 通过从token中获取的用户信息,在判断token是否过期
return {'token': token, 'refresh_token': refresh_token}
else:
return None
def generate_jwt(self, payload, expiry, secret=None):
_payload = {'exp': expiry, 'aud': 'admin'}
_payload.update(payload)
if not secret:
secret = self.request.app['JWT_SECRET']
token = jwt.encode(_payload, secret, algorithm='HS256')
return token.decode()
def verify_jwt(self, token, secret=None):
"""
校验jwt
:param token: jwt
:param secret: 密钥
:return: dict: payload
"""
if not secret:
secret = self.request.app['JWT_SECRET']
try:
payload = jwt.decode(token, secret, audience='admin', algorithms=['HS256'])
# 解析token校验过期时间,过期后会抛异常
except Exception:
payload = None
return payload
class AppAuthorization(AuthorizationResource):
"""app中使用jwt的加密解密"""
def __init__(self, request):
super().__init__(request)
self.days = self.request.app['JWT_REFRESH_DAYS']
def generate_jwt(self, payload, expiry, secret=None):
_payload = {'exp': expiry, 'aud': 'app'}
_payload.update(payload)
if not secret:
secret = self.request.app['JWT_SECRET']
token = jwt.encode(_payload, secret, algorithm='HS256')
return token.decode()
def verify_jwt(self, token, secret=None):
"""
校验jwt
:param token: jwt
:param secret: 密钥
:return: dict: payload
"""
if not secret:
secret = self.request.app['JWT_SECRET']
try:
payload = jwt.decode(token, secret, audience='app', algorithms=['HS256'])
# 解析token校验过期时间,过期后会抛异常
except Exception as e:
payload = None
return payload
class PermissionAuthentication():
"""admin中token装饰器使用"""
def __init__(self, request):
self.request = request
def jwt_authentication(self):
authorization = self.request.headers.get('Authorization')
if authorization:
token = authorization.strip()[7:]
payload = self.verify_jwt(token)
if payload:
self.request['token'] = payload.get('token')
self.request['id'] = payload.get('id')
self.request['is_refresh_token'] = payload.get('refresh')
self.request['permission'] = payload.get('permission')
self.request['duration'] = payload.get('duration', None)
return 1
else:
if authorization.startswith('Bearer '): # token过期提示 前端请求头携带Authorization,值以'Bearer '开头
return 3
elif authorization.startswith('Rearer '): # refreshtoken过期提示 前端请求头携带Authorization,值以'Rearer '开头
return 4
else:
return 0
class AdminPermissionAuthentication(Authorization, PermissionAuthentication):
"""admin中生成token使用"""
pass
class AppPermissionAuthentication(AppAuthorization, PermissionAuthentication):
"""app中生成token使用"""
pass
def permission_authentication(func):
"""后台管理"""
@wraps(func)
def wrapper(*args, **kwargs):
request = args[0]
pa = AdminPermissionAuthentication(request)
result = pa.jwt_authentication()
if result == 1:
return func(*args, **kwargs)
elif result == 3:
return web.json_response({"status": True, "error": "token过期"})
elif result == 4:
return web.json_response({"status": True, "error": "refresh_token过期"})
else:
return web.json_response({"status": False, "error": "no permission"})
return wrapper
def app_permission_authentication(func):
"""app"""
@wraps(func)
def wrapper(*args, **kwargs):
request = args[0]
pa = AppPermissionAuthentication(request)
result = pa.jwt_authentication()
if result == 1:
return func(*args, **kwargs)
elif result == 3:
return web.json_response({"status": True, "error": "token过期"})
elif result == 4:
return web.json_response({"status": True, "error": "refresh_token过期"})
else:
return web.json_response({"status": False, "error": "no permission"})
return wrapper
def id_vip(duration):
now_time = time.strftime('%Y-%m-%d', time.localtime(time.time()))
# 时长小于当前时间过期
if not duration or duration < now_time:
return False
return True
def vip_permission(func):
@wraps(func)
def wrapper(*args, **kwargs):
request = args[0]
is_refresh_token = request.get("is_refresh_token")
if is_refresh_token:
return func(*args, **kwargs)
duration = request.get("duration")
duration = id_vip(duration)
if request.get('permission') != 3 or not duration:
return web.json_response({"status": False, "error": "username非vip"})
else:
return func(*args, **kwargs)
return wrapper