1
1
#!/usr/bin/env python3
2
2
# -*- coding: utf-8 -*-
3
- from fastapi import Request
3
+ from fastapi import Request , Response
4
4
from fastapi .security import HTTPBasicCredentials
5
5
from starlette .background import BackgroundTask , BackgroundTasks
6
6
@@ -38,12 +38,14 @@ async def swagger_login(*, obj: HTTPBasicCredentials) -> tuple[str, User]:
38
38
raise errors .AuthorizationError (msg = '用户名或密码有误' )
39
39
elif not current_user .status :
40
40
raise errors .AuthorizationError (msg = '用户已被锁定, 请联系统管理员' )
41
- access_token , _ = await create_access_token (str (current_user .id ), multi_login = current_user .is_multi_login )
41
+ access_token = await create_access_token (str (current_user .id ), current_user .is_multi_login )
42
42
await user_dao .update_login_time (db , obj .username )
43
- return access_token , current_user
43
+ return access_token . access_token , current_user
44
44
45
45
@staticmethod
46
- async def login (* , request : Request , obj : AuthLoginParam , background_tasks : BackgroundTasks ) -> GetLoginToken :
46
+ async def login (
47
+ * , request : Request , response : Response , obj : AuthLoginParam , background_tasks : BackgroundTasks
48
+ ) -> GetLoginToken :
47
49
async with async_db_session .begin () as db :
48
50
try :
49
51
current_user = await user_dao .get_by_username (db , obj .username )
@@ -61,14 +63,8 @@ async def login(*, request: Request, obj: AuthLoginParam, background_tasks: Back
61
63
if captcha_code .lower () != obj .captcha .lower ():
62
64
raise errors .CustomError (error = CustomErrorCode .CAPTCHA_ERROR )
63
65
current_user_id = current_user .id
64
- access_token , access_token_expire_time = await create_access_token (
65
- str (current_user_id ), multi_login = current_user .is_multi_login
66
- )
67
- refresh_token , refresh_token_expire_time = await create_refresh_token (
68
- sub = str (current_user_id ),
69
- expire_time = access_token_expire_time ,
70
- multi_login = current_user .is_multi_login ,
71
- )
66
+ access_token = await create_access_token (str (current_user_id ), current_user .is_multi_login )
67
+ refresh_token = await create_refresh_token (str (current_user_id ), current_user .is_multi_login )
72
68
except errors .NotFoundError as e :
73
69
raise errors .NotFoundError (msg = e .msg )
74
70
except (errors .AuthorizationError , errors .CustomError ) as e :
@@ -102,19 +98,29 @@ async def login(*, request: Request, obj: AuthLoginParam, background_tasks: Back
102
98
)
103
99
await redis_client .delete (f'{ admin_settings .CAPTCHA_LOGIN_REDIS_PREFIX } :{ request .state .ip } ' )
104
100
await user_dao .update_login_time (db , obj .username )
101
+ response .set_cookie (
102
+ settings .COOKIE_REFRESH_TOKEN_KEY ,
103
+ refresh_token .refresh_token ,
104
+ settings .COOKIE_REFRESH_TOKEN_EXPIRE_SECONDS ,
105
+ refresh_token .refresh_token_expire_time ,
106
+ )
105
107
await db .refresh (current_user )
106
108
data = GetLoginToken (
107
- access_token = access_token ,
108
- refresh_token = refresh_token ,
109
- access_token_expire_time = access_token_expire_time ,
110
- refresh_token_expire_time = refresh_token_expire_time ,
109
+ access_token = access_token .access_token ,
110
+ access_token_expire_time = access_token .access_token_expire_time ,
111
111
user = current_user , # type: ignore
112
112
)
113
113
return data
114
114
115
115
@staticmethod
116
- async def new_token (* , request : Request , refresh_token : str ) -> GetNewToken :
117
- user_id = jwt_decode (refresh_token )
116
+ async def new_token (* , request : Request , response : Response ) -> GetNewToken :
117
+ refresh_token = request .cookies .get (settings .COOKIE_REFRESH_TOKEN_KEY )
118
+ if not refresh_token :
119
+ raise errors .TokenError (msg = 'Refresh Token 丢失,请重新登录' )
120
+ try :
121
+ user_id = jwt_decode (refresh_token )
122
+ except Exception :
123
+ raise errors .TokenError (msg = 'Refresh Token 无效' )
118
124
if request .user .id != user_id :
119
125
raise errors .TokenError (msg = 'Refresh Token 无效' )
120
126
async with async_db_session () as db :
@@ -130,23 +136,34 @@ async def new_token(*, request: Request, refresh_token: str) -> GetNewToken:
130
136
refresh_token = refresh_token ,
131
137
multi_login = current_user .is_multi_login ,
132
138
)
139
+ response .set_cookie (
140
+ settings .COOKIE_REFRESH_TOKEN_KEY ,
141
+ new_token .new_refresh_token ,
142
+ settings .COOKIE_REFRESH_TOKEN_EXPIRE_SECONDS ,
143
+ new_token .new_refresh_token_expire_time ,
144
+ )
133
145
data = GetNewToken (
134
146
access_token = new_token .new_access_token ,
135
147
access_token_expire_time = new_token .new_access_token_expire_time ,
136
- refresh_token = new_token .new_refresh_token ,
137
- refresh_token_expire_time = new_token .new_refresh_token_expire_time ,
138
148
)
139
149
return data
140
150
141
151
@staticmethod
142
- async def logout (* , request : Request ) -> None :
152
+ async def logout (* , request : Request , response : Response ) -> None :
143
153
token = await get_token (request )
154
+ refresh_token = request .cookies .get (settings .COOKIE_REFRESH_TOKEN_KEY )
155
+ response .delete_cookie (settings .COOKIE_REFRESH_TOKEN_KEY )
144
156
if request .user .is_multi_login :
145
157
key = f'{ settings .TOKEN_REDIS_PREFIX } :{ request .user .id } :{ token } '
146
158
await redis_client .delete (key )
159
+ if refresh_token :
160
+ key = f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ request .user .id } :{ refresh_token } '
161
+ await redis_client .delete (key )
147
162
else :
148
163
key_prefix = f'{ settings .TOKEN_REDIS_PREFIX } :{ request .user .id } :'
149
164
await redis_client .delete_prefix (key_prefix )
165
+ key_prefix = f'{ settings .TOKEN_REFRESH_REDIS_PREFIX } :{ request .user .id } :'
166
+ await redis_client .delete_prefix (key_prefix )
150
167
151
168
152
169
auth_service = AuthService ()
0 commit comments