py.lib.aw_web_tools
2025-03-09
Parent:b9fd029be707
py.lib.aw_web_tools/src/aw_web_tools/jwt_helper.py
.. 1.202503.5 - Убран devel_mode в конструкторе класса `SimpleTmplWrapper`, поскольку он бесполезен для поставленной задачи + Добавлена фабрака объектов. Этим методом имеется возможность перечитывать страницы шаблона при каждом вызове его. Это помогает в отладке шаблонов.
| awgur@0 | 1 # coding: utf-8 |
| awgur@0 | 2 |
| awgur@0 | 3 import jwt |
| awgur@0 | 4 from datetime import datetime, timedelta |
| awgur@0 | 5 from typing import Optional |
| awgur@0 | 6 |
| awgur@5 | 7 from . import Error |
| awgur@5 | 8 |
| awgur@0 | 9 JWT_HASH_ALGO = 'HS512' |
| awgur@0 | 10 |
| awgur@0 | 11 |
| awgur@5 | 12 class JWTError(Error): |
| awgur@0 | 13 pass |
| awgur@0 | 14 |
| awgur@0 | 15 |
| awgur@0 | 16 class JWTAuthError(JWTError): |
| awgur@0 | 17 """\ |
| awgur@8 | 18 Провалена проверка токена на допустимость по подписи, времени действия или прочее |
| awgur@0 | 19 """ |
| awgur@0 | 20 |
| awgur@0 | 21 |
| awgur@0 | 22 class JWTHelper(object): |
| awgur@0 | 23 def __init__(self, key: str): |
| awgur@0 | 24 self.key = key |
| awgur@0 | 25 |
| awgur@0 | 26 def encode(self, data: dict, timeout: Optional[int] = None) -> str: |
| awgur@0 | 27 if timeout is not None: |
| awgur@0 | 28 data['exp'] = datetime.utcnow() + timedelta(seconds=timeout) |
| awgur@0 | 29 |
| awgur@0 | 30 return jwt.encode(data, key=self.key, algorithm=JWT_HASH_ALGO) |
| awgur@0 | 31 |
| awgur@0 | 32 def decode(self, token: str, check_timeout: bool = False) -> dict: |
| awgur@0 | 33 opts = { |
| awgur@0 | 34 'algorithms': [JWT_HASH_ALGO, ] |
| awgur@0 | 35 } |
| awgur@0 | 36 |
| awgur@0 | 37 if check_timeout: |
| awgur@0 | 38 opts['options'] = {'require': {'exp'}} |
| awgur@0 | 39 |
| awgur@0 | 40 if token is None: |
| awgur@0 | 41 raise JWTAuthError('Ключ отсутствует') |
| awgur@0 | 42 else: |
| awgur@0 | 43 token = token.encode('utf-8') |
| awgur@0 | 44 |
| awgur@0 | 45 try: |
| awgur@0 | 46 return jwt.decode(jwt=token, key=self.key, **opts) |
| awgur@0 | 47 |
| awgur@0 | 48 except (jwt.InvalidIssuerError, jwt.InvalidSignatureError, jwt.ExpiredSignatureError) as e: |
| awgur@0 | 49 raise JWTAuthError(str(e)) |
| awgur@0 | 50 |
| awgur@0 | 51 except jwt.PyJWTError as e: |
| awgur@0 | 52 raise JWTError(f'{type(e).__name__}: {e}') |
| awgur@0 | 53 |
| awgur@0 | 54 @classmethod |
| awgur@0 | 55 def make_fabric(cls, key: str): |
| awgur@0 | 56 def f(): |
| awgur@0 | 57 return cls(key=key) |
| awgur@0 | 58 |
| awgur@0 | 59 return f |