Bootstrap

使用框架aiohttp app中认证机制及判断是否是vip访问接口

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

;