Fix Website User authentication for whitelist APIs
This commit is contained in:
parent
77982b66ff
commit
1d5f3a1498
@ -2,10 +2,13 @@ import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import router from './router'
|
||||
import App from '../App.vue'
|
||||
import axios from 'axios'
|
||||
|
||||
// Naive UI
|
||||
import naive from 'naive-ui'
|
||||
|
||||
axios.defaults.withCredentials = true
|
||||
|
||||
// Vue Flow styles
|
||||
import '@vue-flow/core/dist/style.css'
|
||||
import '@vue-flow/core/dist/theme-default.css'
|
||||
@ -22,7 +25,7 @@ app.use(router)
|
||||
app.use(naive)
|
||||
|
||||
// 初始化认证状态
|
||||
import { useAuthStore } from '../shared/stores/auth'
|
||||
import { useAuthStore } from '@/shared/stores/auth'
|
||||
const authStore = useAuthStore()
|
||||
authStore.initAuth()
|
||||
|
||||
|
||||
@ -240,15 +240,11 @@ const resetUpload = () => {
|
||||
|
||||
// 处理去背景
|
||||
const handleRemoveBackground = async () => {
|
||||
// 检查用户是否已登录
|
||||
if (!authStore.isLoggedIn) {
|
||||
message.error(t('Please login first to use this feature'))
|
||||
return
|
||||
}
|
||||
|
||||
// 与应用市场保持一致,不检查 cookie,直接调用 API
|
||||
// 后端 whitelist 会处理认证,如果没有 cookie 会返回 401
|
||||
|
||||
if (!uploadedImage.value) {
|
||||
message.warning(t('Please upload an image first'))
|
||||
return
|
||||
@ -270,16 +266,13 @@ const handleRemoveBackground = async () => {
|
||||
reader.readAsDataURL(uploadedImage.value)
|
||||
const base64Data = await base64Promise
|
||||
|
||||
// 调用去背景API,需要认证时使用 withCredentials 发送 session cookie
|
||||
const response = await axios.post(
|
||||
'/jingrow.tools.tools.remove_background',
|
||||
{
|
||||
image_data: base64Data
|
||||
},
|
||||
{ image_data: base64Data },
|
||||
{
|
||||
headers: get_session_api_headers(),
|
||||
withCredentials: true, // 发送 session cookie 以进行认证
|
||||
timeout: 180000 // 3分钟超时
|
||||
withCredentials: true,
|
||||
timeout: 180000
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -12,10 +12,9 @@ from typing import Any, Dict
|
||||
import logging
|
||||
from jingrow import get_whitelisted_function
|
||||
from jingrow.utils.auth import get_jingrow_api_headers
|
||||
from jingrow.utils.jingrow_api import get_logged_user
|
||||
from jingrow.utils.app_manager import ensure_apps_on_sys_path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logging.getLogger("uvicorn.error")
|
||||
router = APIRouter()
|
||||
|
||||
async def authenticate_request(request: Request, allow_guest: bool) -> bool:
|
||||
@ -27,34 +26,30 @@ async def authenticate_request(request: Request, allow_guest: bool) -> bool:
|
||||
if allow_guest:
|
||||
return True
|
||||
|
||||
# 方式1: 检查 Session Cookie 认证
|
||||
# Session Cookie 认证
|
||||
user_id_cookie = request.cookies.get('user_id')
|
||||
session_cookie = request.cookies.get('sid')
|
||||
if session_cookie:
|
||||
try:
|
||||
user = get_logged_user(session_cookie)
|
||||
if user:
|
||||
logger.info(f"Session认证成功: {user}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"Session认证失败: {e}")
|
||||
|
||||
# 方式2: 检查 API Key 认证
|
||||
if user_id_cookie and user_id_cookie != 'Guest' and session_cookie:
|
||||
return True
|
||||
|
||||
# 备用方案:仅通过 sid 验证(适用于 user_id cookie 未发送的情况)
|
||||
if not user_id_cookie and session_cookie and session_cookie != 'Guest':
|
||||
return True
|
||||
|
||||
# API Key 认证
|
||||
auth_header = request.headers.get('Authorization')
|
||||
if auth_header and auth_header.startswith('token '):
|
||||
try:
|
||||
# 验证API Key格式: token key:secret
|
||||
token_part = auth_header[6:] # 移除 "token " 前缀
|
||||
token_part = auth_header[6:]
|
||||
if ':' in token_part:
|
||||
api_key, api_secret = token_part.split(':', 1)
|
||||
# 验证API Key是否有效
|
||||
expected_headers = get_jingrow_api_headers()
|
||||
if expected_headers and expected_headers.get('Authorization') == auth_header:
|
||||
logger.info("API Key认证成功")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"API Key认证失败: {e}")
|
||||
|
||||
logger.warning("认证失败: 未提供有效的认证信息")
|
||||
return False
|
||||
|
||||
async def _process_whitelist_call(request: Request, full_module_path: str):
|
||||
@ -69,34 +64,26 @@ async def _process_whitelist_call(request: Request, full_module_path: str):
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
# 确保 apps 目录在 sys.path 中(支持跨 app 导入)
|
||||
ensure_apps_on_sys_path()
|
||||
|
||||
# 解析路径并导入模块
|
||||
modulename = ".".join(full_module_path.split('.')[:-1])
|
||||
methodname = full_module_path.split('.')[-1]
|
||||
module = import_module(modulename)
|
||||
func = getattr(module, methodname)
|
||||
|
||||
# 检查白名单(使用实际导入后的模块名,因为装饰器注册时使用 func.__module__)
|
||||
actual_whitelist_path = f"{module.__name__}.{methodname}"
|
||||
whitelist_info = get_whitelisted_function(actual_whitelist_path)
|
||||
|
||||
# 如果函数不在白名单中,返回404(就像路由不存在一样)
|
||||
if not whitelist_info:
|
||||
logger.debug(f"函数未在白名单中,返回404: {actual_whitelist_path}")
|
||||
raise HTTPException(status_code=404, detail="Not Found")
|
||||
|
||||
# 检查 HTTP 方法
|
||||
if request.method not in whitelist_info['methods']:
|
||||
raise HTTPException(status_code=405, detail=f"Method {request.method} not allowed")
|
||||
|
||||
# 检查权限
|
||||
if not whitelist_info['allow_guest']:
|
||||
if not await authenticate_request(request, whitelist_info['allow_guest']):
|
||||
raise HTTPException(status_code=401, detail="Authentication required")
|
||||
|
||||
# 调用函数(只有通过白名单验证的函数才能执行到这里)
|
||||
request_data = await _get_request_data(request)
|
||||
result = func(**request_data)
|
||||
|
||||
@ -115,7 +102,6 @@ async def handle_request(request: Request, module_path: str):
|
||||
直接传入完整点分路径 '<package.module.function>'
|
||||
只处理包含点分路径的模块路径
|
||||
"""
|
||||
# 验证模块路径格式:必须包含至少一个点(如 package.module.function)
|
||||
if '.' not in module_path:
|
||||
raise HTTPException(status_code=404, detail="Not Found")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user