11
11
from typing_extensions import Annotated
12
12
13
13
from backend .app .common .exception .errors import AuthorizationError , TokenError
14
+ from backend .app .common .redis import redis_client
14
15
from backend .app .core .conf import settings
15
16
from backend .app .crud .crud_user import UserDao
16
17
from backend .app .database .db_mysql import CurrentSession
@@ -42,28 +43,34 @@ def password_verify(plain_password: str, hashed_password: str) -> bool:
42
43
return pwd_context .verify (plain_password , hashed_password )
43
44
44
45
45
- def create_access_token (data : int | Any , expires_delta : timedelta | None = None ) -> str :
46
+ async def create_access_token (sub : int | Any , data : dict , expires_delta : timedelta | None = None ) -> str :
46
47
"""
47
48
Generate encryption token
48
49
50
+ :param sub: The subject/userid of the JWT
49
51
:param data: Data transferred to the token
50
52
:param expires_delta: Increased expiry time
51
53
:return:
52
54
"""
53
55
if expires_delta :
54
56
expires = datetime .utcnow () + expires_delta
57
+ expire_seconds = expires_delta .total_seconds ()
55
58
else :
56
- expires = datetime .utcnow () + timedelta (settings .TOKEN_EXPIRE_MINUTES )
57
- to_encode = {'exp' : expires , 'sub' : str (data [0 ]), 'role_ids' : str (data [1 ])}
58
- encoded_jwt = jwt .encode (to_encode , settings .TOKEN_SECRET_KEY , settings .TOKEN_ALGORITHM )
59
- return encoded_jwt
60
-
61
-
62
- async def get_current_user (db : CurrentSession , token : str = Depends (oauth2_schema )) -> User :
59
+ expires = datetime .utcnow () + timedelta (seconds = settings .TOKEN_EXPIRE_MINUTES )
60
+ expire_seconds = settings .TOKEN_EXPIRE_SECONDS
61
+ to_encode = {'exp' : expires , 'sub' : str (sub ), ** data }
62
+ token = jwt .encode (to_encode , settings .TOKEN_SECRET_KEY , settings .TOKEN_ALGORITHM )
63
+ if sub not in settings .TOKEN_WHITE_LIST :
64
+ await redis_client .delete (f'token:{ sub } :*' )
65
+ key = f'token:{ sub } :{ token } '
66
+ await redis_client .setex (key , expire_seconds , token )
67
+ return token
68
+
69
+
70
+ async def jwt_authentication (token : str = Depends (oauth2_schema )):
63
71
"""
64
- Get the current user through tokens
72
+ JWT authentication
65
73
66
- :param db:
67
74
:param token:
68
75
:return:
69
76
"""
@@ -73,8 +80,25 @@ async def get_current_user(db: CurrentSession, token: str = Depends(oauth2_schem
73
80
user_role = payload .get ('role_ids' )
74
81
if not user_id or not user_role :
75
82
raise TokenError
83
+ # 验证token是否有效
84
+ key = f'token:{ user_id } :{ token } '
85
+ valid_token = await redis_client .get (key )
86
+ if not valid_token :
87
+ raise TokenError
88
+ return {'payload' : payload , 'token' : token }
76
89
except (jwt .JWTError , ValidationError ):
77
90
raise TokenError
91
+
92
+
93
+ async def get_current_user (db : CurrentSession , data : dict = Depends (jwt_authentication )) -> User :
94
+ """
95
+ Get the current user through tokens
96
+
97
+ :param db:
98
+ :param data:
99
+ :return:
100
+ """
101
+ user_id = data .get ('payload' ).get ('sub' )
78
102
user = await UserDao .get_user_with_relation (db , user_id = user_id )
79
103
if not user :
80
104
raise TokenError
@@ -97,6 +121,8 @@ async def get_current_is_superuser(user: User = Depends(get_current_user)):
97
121
# User Annotated
98
122
CurrentUser = Annotated [User , Depends (get_current_user )]
99
123
CurrentSuperUser = Annotated [bool , Depends (get_current_is_superuser )]
124
+ # Token dependency injection
125
+ JwtAuthentication = Annotated [dict , Depends (jwt_authentication )]
100
126
# Permission dependency injection
101
127
DependsUser = Depends (get_current_user )
102
128
DependsSuperUser = Depends (get_current_is_superuser )
0 commit comments