@@ -60,11 +60,7 @@ def jwt_encode(payload: dict[str, Any]) -> str:
6060 :param payload: 载荷
6161 :return:
6262 """
63- return jwt .encode (
64- payload ,
65- settings .TOKEN_SECRET_KEY ,
66- settings .TOKEN_ALGORITHM ,
67- )
63+ return jwt .encode (payload , settings .TOKEN_SECRET_KEY , settings .TOKEN_ALGORITHM )
6864
6965
7066def jwt_decode (token : str ) -> TokenPayload :
@@ -75,20 +71,27 @@ def jwt_decode(token: str) -> TokenPayload:
7571 :return:
7672 """
7773 try :
78- payload = jwt .decode (token , settings .TOKEN_SECRET_KEY , algorithms = [settings .TOKEN_ALGORITHM ])
79- session_uuid = payload .get ('session_uuid' ) or 'debug'
74+ payload = jwt .decode (
75+ token ,
76+ settings .TOKEN_SECRET_KEY ,
77+ algorithms = [settings .TOKEN_ALGORITHM ],
78+ options = {'verify_exp' : True },
79+ )
80+ session_uuid = payload .get ('session_uuid' )
8081 user_id = payload .get ('sub' )
81- expire_time = payload .get ('exp' )
82- if not user_id :
82+ expire = payload .get ('exp' )
83+ if not session_uuid or not user_id or not expire :
8384 raise errors .TokenError (msg = 'Token 无效' )
8485 except ExpiredSignatureError :
8586 raise errors .TokenError (msg = 'Token 已过期' )
8687 except (JWTError , Exception ):
8788 raise errors .TokenError (msg = 'Token 无效' )
88- return TokenPayload (id = int (user_id ), session_uuid = session_uuid , expire_time = expire_time )
89+ return TokenPayload (
90+ id = int (user_id ), session_uuid = session_uuid , expire_time = timezone .from_datetime (timezone .to_utc (expire ))
91+ )
8992
9093
91- async def create_access_token (user_id : str , multi_login : bool , ** kwargs ) -> AccessToken :
94+ async def create_access_token (user_id : int , multi_login : bool , ** kwargs ) -> AccessToken :
9295 """
9396 生成加密 token
9497
@@ -101,8 +104,8 @@ async def create_access_token(user_id: str, multi_login: bool, **kwargs) -> Acce
101104 session_uuid = str (uuid4 ())
102105 access_token = jwt_encode ({
103106 'session_uuid' : session_uuid ,
104- 'exp' : expire ,
105- 'sub' : user_id ,
107+ 'exp' : timezone . to_utc ( expire ). timestamp () ,
108+ 'sub' : str ( user_id ) ,
106109 })
107110
108111 if not multi_login :
@@ -117,68 +120,82 @@ async def create_access_token(user_id: str, multi_login: bool, **kwargs) -> Acce
117120 # Token 附加信息单独存储
118121 if kwargs :
119122 await redis_client .setex (
120- f'{ settings .TOKEN_EXTRA_INFO_REDIS_PREFIX } :{ session_uuid } ' ,
123+ f'{ settings .TOKEN_EXTRA_INFO_REDIS_PREFIX } :{ user_id } : { session_uuid } ' ,
121124 settings .TOKEN_EXPIRE_SECONDS ,
122125 json .dumps (kwargs , ensure_ascii = False ),
123126 )
124127
125128 return AccessToken (access_token = access_token , access_token_expire_time = expire , session_uuid = session_uuid )
126129
127130
128- async def create_refresh_token (user_id : str , multi_login : bool ) -> RefreshToken :
131+ async def create_refresh_token (session_uuid : str , user_id : int , multi_login : bool ) -> RefreshToken :
129132 """
130133 生成加密刷新 token,仅用于创建新的 token
131134
135+ :param session_uuid: 会话 UUID
132136 :param user_id: 用户 ID
133137 :param multi_login: 是否允许多端登录
134138 :return:
135139 """
136140 expire = timezone .now () + timedelta (seconds = settings .TOKEN_REFRESH_EXPIRE_SECONDS )
137- refresh_token = jwt_encode ({'exp' : expire , 'sub' : user_id })
141+ refresh_token = jwt_encode ({
142+ 'session_uuid' : session_uuid ,
143+ 'exp' : timezone .to_utc (expire ).timestamp (),
144+ 'sub' : str (user_id ),
145+ })
138146
139147 if not multi_login :
140- key_prefix = f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } '
141- await redis_client .delete_prefix (key_prefix )
148+ await redis_client .delete_prefix (f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } ' )
142149
143150 await redis_client .setex (
144- f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } :{ refresh_token } ' ,
151+ f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } :{ session_uuid } ' ,
145152 settings .TOKEN_REFRESH_EXPIRE_SECONDS ,
146153 refresh_token ,
147154 )
148155 return RefreshToken (refresh_token = refresh_token , refresh_token_expire_time = expire )
149156
150157
151- async def create_new_token (user_id : str , refresh_token : str , multi_login : bool , ** kwargs ) -> NewToken :
158+ async def create_new_token (
159+ refresh_token : str , session_uuid : str , user_id : int , multi_login : bool , ** kwargs
160+ ) -> NewToken :
152161 """
153162 生成新的 token
154163
155- :param user_id: 用户 ID
156164 :param refresh_token: 刷新 token
165+ :param session_uuid: 会话 UUID
166+ :param user_id: 用户 ID
157167 :param multi_login: 是否允许多端登录
158168 :param kwargs: token 附加信息
159169 :return:
160170 """
161- redis_refresh_token = await redis_client .get (f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } :{ refresh_token } ' )
171+ redis_refresh_token = await redis_client .get (f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } :{ session_uuid } ' )
162172 if not redis_refresh_token or redis_refresh_token != refresh_token :
163173 raise errors .TokenError (msg = 'Refresh Token 已过期,请重新登录' )
174+
175+ await redis_client .delete (f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ user_id } :{ session_uuid } ' )
176+ await redis_client .delete (f'{ settings .TOKEN_REDIS_PREFIX } :{ user_id } :{ session_uuid } ' )
177+
164178 new_access_token = await create_access_token (user_id , multi_login , ** kwargs )
179+ new_refresh_token = await create_refresh_token (new_access_token .session_uuid , user_id , multi_login )
165180 return NewToken (
166181 new_access_token = new_access_token .access_token ,
167182 new_access_token_expire_time = new_access_token .access_token_expire_time ,
183+ new_refresh_token = new_refresh_token .refresh_token ,
184+ new_refresh_token_expire_time = new_refresh_token .refresh_token_expire_time ,
168185 session_uuid = new_access_token .session_uuid ,
169186 )
170187
171188
172- async def revoke_token (user_id : str , session_uuid : str ) -> None :
189+ async def revoke_token (user_id : int , session_uuid : str ) -> None :
173190 """
174191 撤销 token
175192
176193 :param user_id: 用户 ID
177194 :param session_uuid: 会话 ID
178195 :return:
179196 """
180- token_key = f'{ settings .TOKEN_REDIS_PREFIX } :{ user_id } :{ session_uuid } '
181- await redis_client .delete (token_key )
197+ await redis_client . delete ( f'{ settings .TOKEN_REDIS_PREFIX } :{ user_id } :{ session_uuid } ' )
198+ await redis_client .delete (f' { settings . TOKEN_EXTRA_INFO_REDIS_PREFIX } : { user_id } : { session_uuid } ' )
182199
183200
184201def get_token (request : Request ) -> str :
0 commit comments