diff --git a/backend/app/admin/api/v1/auth/auth.py b/backend/app/admin/api/v1/auth/auth.py index e513c267..8ad88e49 100644 --- a/backend/app/admin/api/v1/auth/auth.py +++ b/backend/app/admin/api/v1/auth/auth.py @@ -47,8 +47,8 @@ async def get_codes(db: CurrentSession, request: Request) -> ResponseSchemaModel @router.post('/refresh', summary='刷新 token') -async def refresh_token(db: CurrentSession, request: Request) -> ResponseSchemaModel[GetNewToken]: - data = await auth_service.refresh_token(db=db, request=request) +async def refresh_token(db: CurrentSession, request: Request, response: Response) -> ResponseSchemaModel[GetNewToken]: + data = await auth_service.refresh_token(db=db, request=request, response=response) return response_base.success(data=data) diff --git a/backend/app/admin/service/auth_service.py b/backend/app/admin/service/auth_service.py index 859b22d1..75a8971a 100644 --- a/backend/app/admin/service/auth_service.py +++ b/backend/app/admin/service/auth_service.py @@ -142,7 +142,7 @@ class AuthService: raise errors.NotFoundError(msg=e.msg) except (errors.RequestError, errors.CustomError) as e: if not user: - log.error('登陆错误: 用户密码有误') + log.error(f'登陆错误: {e.msg}') task = BackgroundTask( login_log_service.create, user_uuid=user.uuid if user else uuid4_str(), @@ -199,25 +199,30 @@ class AuthService: return list(codes) @staticmethod - async def refresh_token(*, db: AsyncSession, request: Request) -> GetNewToken: + async def refresh_token(*, db: AsyncSession, request: Request, response: Response) -> GetNewToken: """ 刷新令牌 :param db: 数据库会话 :param request: FastAPI 请求对象 + :param response: FastAPI 响应对象 :return: """ refresh_token = request.cookies.get(settings.COOKIE_REFRESH_TOKEN_KEY) if not refresh_token: raise errors.RequestError(msg='Refresh Token 已过期,请重新登录') - token_payload = jwt_decode(refresh_token) - user = await user_dao.get(db, token_payload.id) + token_payload = jwt_decode(refresh_token) + user = await user_dao.get(db, token_payload.user_id) if not user: raise errors.NotFoundError(msg='用户不存在') if not user.status: raise errors.AuthorizationError(msg='用户已被锁定, 请联系统管理员') - if not user.is_multi_login and await redis_client.get_prefix(f'{settings.TOKEN_REDIS_PREFIX}:{user.id}:*'): + if not user.is_multi_login and [ + key + for key in await redis_client.get_prefix(f'{settings.TOKEN_REDIS_PREFIX}:{user.id}:*') + if not key.endswith(f':{token_payload.session_uuid}') + ]: raise errors.ForbiddenError(msg='此用户已在异地登录,请重新登录并及时修改密码') new_token = await create_new_token( refresh_token, @@ -233,6 +238,13 @@ class AuthService: browser=ctx.browser, device_type=ctx.device, ) + response.set_cookie( + key=settings.COOKIE_REFRESH_TOKEN_KEY, + value=new_token.new_refresh_token, + max_age=settings.COOKIE_REFRESH_TOKEN_EXPIRE_SECONDS, + expires=timezone.to_utc(new_token.new_refresh_token_expire_time), + httponly=True, + ) data = GetNewToken( access_token=new_token.new_access_token, access_token_expire_time=new_token.new_access_token_expire_time, @@ -252,7 +264,7 @@ class AuthService: try: token = get_token(request) token_payload = jwt_decode(token) - user_id = token_payload.id + user_id = token_payload.user_id session_uuid = token_payload.session_uuid refresh_token = request.cookies.get(settings.COOKIE_REFRESH_TOKEN_KEY) except errors.TokenError: