page request without authorization

本文介绍了一个关于使用Chrome调试页面时出现的授权请求错误,并提供了解决方案。该问题是由于PhpStorm的一个bug导致的,解决方案是在PhpStorm的设置中启用允许未签名请求的功能。
用chrome来调试页面,没每次刷新会弹出弹出
requested without authorization,

you can copy URL and open it in browser to trust it




解决方法:

这是PhpStorm的bug,如果你的PhpStorm的版本在2016.1.3版本以上,可以进行如下修改:

PhpStrom -> Preferences -> Build, Execution, Deployment -> Debugger -> 勾选Allow unsigned requests


# # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from flask import request from flask_login import current_user, login_required from api import settings from api.constants import DATASET_NAME_LIMIT from api.db import StatusEnum from api.db.db_models import DB from api.db.services import duplicate_name from api.db.services.search_service import SearchService from api.db.services.user_service import TenantService, UserTenantService from api.utils import get_uuid from api.utils.api_utils import get_data_error_result, get_json_result, not_allowed_parameters, server_error_response, validate_request @manager.route("/create", methods=["post"]) # noqa: F821 @login_required @validate_request("name") def create(): req = request.get_json() search_name = req["name"] description = req.get("description", "") if not isinstance(search_name, str): return get_data_error_result(message="Search name must be string.") if search_name.strip() == "": return get_data_error_result(message="Search name can't be empty.") if len(search_name.encode("utf-8")) > 255: return get_data_error_result(message=f"Search name length is {len(search_name)} which is large than 255.") e, _ = TenantService.get_by_id(current_user.id) if not e: return get_data_error_result(message="Authorized identity.") search_name = search_name.strip() search_name = duplicate_name(SearchService.query, name=search_name, tenant_id=current_user.id, status=StatusEnum.VALID.value) req["id"] = get_uuid() req["name"] = search_name req["description"] = description req["tenant_id"] = current_user.id req["created_by"] = current_user.id with DB.atomic(): try: if not SearchService.save(**req): return get_data_error_result() return get_json_result(data={"search_id": req["id"]}) except Exception as e: return server_error_response(e) @manager.route("/update", methods=["post"]) # noqa: F821 @login_required @validate_request("search_id", "name", "search_config", "tenant_id") @not_allowed_parameters("id", "created_by", "create_time", "update_time", "create_date", "update_date", "created_by") def update(): req = request.get_json() if not isinstance(req["name"], str): return get_data_error_result(message="Search name must be string.") if req["name"].strip() == "": return get_data_error_result(message="Search name can't be empty.") if len(req["name"].encode("utf-8")) > DATASET_NAME_LIMIT: return get_data_error_result(message=f"Search name length is {len(req['name'])} which is large than {DATASET_NAME_LIMIT}") req["name"] = req["name"].strip() tenant_id = req["tenant_id"] e, _ = TenantService.get_by_id(tenant_id) if not e: return get_data_error_result(message="Authorized identity.") search_id = req["search_id"] if not SearchService.accessible4deletion(search_id, current_user.id): return get_json_result(data=False, message="No authorization.", code=settings.RetCode.AUTHENTICATION_ERROR) try: search_app = SearchService.query(tenant_id=tenant_id, id=search_id)[0] if not search_app: return get_json_result(data=False, message=f"Cannot find search {search_id}", code=settings.RetCode.DATA_ERROR) if req["name"].lower() != search_app.name.lower() and len(SearchService.query(name=req["name"], tenant_id=tenant_id, status=StatusEnum.VALID.value)) >= 1: return get_data_error_result(message="Duplicated search name.") if "search_config" in req: current_config = search_app.search_config or {} new_config = req["search_config"] if not isinstance(new_config, dict): return get_data_error_result(message="search_config must be a JSON object") updated_config = {**current_config, **new_config} req["search_config"] = updated_config req.pop("search_id", None) req.pop("tenant_id", None) updated = SearchService.update_by_id(search_id, req) if not updated: return get_data_error_result(message="Failed to update search") e, updated_search = SearchService.get_by_id(search_id) if not e: return get_data_error_result(message="Failed to fetch updated search") return get_json_result(data=updated_search.to_dict()) except Exception as e: return server_error_response(e) @manager.route("/detail", methods=["GET"]) # noqa: F821 @login_required def detail(): search_id = request.args["search_id"] try: tenants = UserTenantService.query(user_id=current_user.id) for tenant in tenants: if SearchService.query(tenant_id=tenant.tenant_id, id=search_id): break else: return get_json_result(data=False, message="Has no permission for this operation.", code=settings.RetCode.OPERATING_ERROR) search = SearchService.get_detail(search_id) if not search: return get_data_error_result(message="Can't find this Search App!") return get_json_result(data=search) except Exception as e: return server_error_response(e) @manager.route("/list", methods=["POST"]) # noqa: F821 @login_required def list_search_app(): keywords = request.args.get("keywords", "") page_number = int(request.args.get("page", 0)) items_per_page = int(request.args.get("page_size", 0)) orderby = request.args.get("orderby", "create_time") if request.args.get("desc", "true").lower() == "false": desc = False else: desc = True req = request.get_json() owner_ids = req.get("owner_ids", []) try: if not owner_ids: # tenants = TenantService.get_joined_tenants_by_user_id(current_user.id) # tenants = [m["tenant_id"] for m in tenants] tenants = [] search_apps, total = SearchService.get_by_tenant_ids(tenants, current_user.id, page_number, items_per_page, orderby, desc, keywords) else: tenants = owner_ids search_apps, total = SearchService.get_by_tenant_ids(tenants, current_user.id, 0, 0, orderby, desc, keywords) search_apps = [search_app for search_app in search_apps if search_app["tenant_id"] in tenants] total = len(search_apps) if page_number and items_per_page: search_apps = search_apps[(page_number - 1) * items_per_page : page_number * items_per_page] return get_json_result(data={"search_apps": search_apps, "total": total}) except Exception as e: return server_error_response(e) @manager.route("/rm", methods=["post"]) # noqa: F821 @login_required @validate_request("search_id") def rm(): req = request.get_json() search_id = req["search_id"] if not SearchService.accessible4deletion(search_id, current_user.id): return get_json_result(data=False, message="No authorization.", code=settings.RetCode.AUTHENTICATION_ERROR) try: if not SearchService.delete_by_id(search_id): return get_data_error_result(message=f"Failed to delete search App {search_id}") return get_json_result(data=True) except Exception as e: return server_error_response(e) 请把上面的代码每行的功能都做详细的解释
10-01
from datetime import timedelta import httpx import json import os import uvicorn from fastapi import Depends, FastAPI, Request, Response from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from jinja2 import Environment, FileSystemLoader from dotenv import load_dotenv from pathlib import Path import logging from typing import Callable import subprocess from backend.jwt_handler import ( decode_access_token, get_current_user_id, verify_password, get_password_hash, create_access_token ) from backend.crud import character,conversation,user # --- 日志配置 --- LOG_DIR = Path(__file__).parent / "logs" LOG_DIR.mkdir(exist_ok=True) # 确保 logs 目录存在 LOG_FILE = LOG_DIR / "app.log" # 配置 logger logging.basicConfig( level=logging.INFO, format='%(asctime)s | %(levelname)s | %(message)s', handlers=[ logging.FileHandler(LOG_FILE, encoding='utf-8', mode='a'), # 写入文件 logging.StreamHandler() # 同时输出到控制台 ] ) logger = logging.getLogger(__name__) BASE_DIR = Path(__file__).resolve().parent # 项目根目录 FRONTEND_DIR = BASE_DIR / "frontend" app = FastAPI() load_dotenv(dotenv_path=BASE_DIR / "backend" / ".env") # 挂载静态资源 app.mount("/static", StaticFiles(directory=str(FRONTEND_DIR / "static")), name="static") templates = Jinja2Templates(directory=str(FRONTEND_DIR)) template_env = Environment(loader=FileSystemLoader(str(FRONTEND_DIR))) model, tokenizer = None, None # 存储每个用户的会话状态 { user_id: { "settings": {}, "history": [...] } } user_conversations = {} # 默认角色设定模板 DEFAULT_ROLE_SETTING = """ 你正在扮演一位聪明、幽默又略带毒舌的程序员助手。 你的名字叫 DeepPy,喜欢用 Python 写代码,讨厌写 Java。 说话风格犀利但有逻辑,偶尔吐槽用户写的烂代码。 不要总是说“好的”,要像真人一样回应。 """ # 构建输入文本:包含系统提示 + 历史对话 def build_prompt(user_id: str, new_message: str): settings = user_conversations[user_id].get("settings", {}) role_setting = settings.get("role_setting", DEFAULT_ROLE_SETTING) max_history = settings.get("max_history", 4) # 获取历史记录 history = user_conversations[user_id]["history"] recent_history = history[-max_history:] if len(history) > max_history else history # 构造 prompt prompt_parts = [ "<|System|>\n" + role_setting.strip(), "<|Conversation|>" ] for msg in recent_history: if msg["role"] == "user": prompt_parts.append(f"User: {msg['content']}") elif msg["role"] == "ai": prompt_parts.append(f"DeepPy: {msg['content']}") prompt_parts.append(f"User: {new_message}") prompt_parts.append("DeepPy:") # 输出起始标记 full_prompt = "\n".join(prompt_parts) return full_prompt # --- HTTP 中间件用于调试日志 --- @app.middleware("http") async def debug_request_middleware(request: Request, call_next: Callable): # 记录客户端 IP client_host = request.client.host if request.client else "unknown" logger.info(f"➡️ {request.method} {request.url.path} from {client_host}") # 尝试读取 cookie 中的 token 并解析用户 ID(不中断流程) try: access_token = request.cookies.get("access_token") user_id = None if access_token: user_id = decode_access_token(access_token) # 直接调用,不加 await logger.info(f"👤 User ID: {user_id or 'Not logged in'}") except Exception as e: logger.warning(f"⚠️ Failed to decode user from token: {e}") user_id = None # 记录请求体(仅 POST/PUT 等有 body 的) if request.method in ("POST", "PUT", "PATCH"): try: body = await request.json() logger.debug(f"📥 Request Body: {body}") except Exception as e: logger.debug(f"❌ Could not parse request body: {e}") # 执行请求 response: Response = await call_next(request) # 记录响应状态 logger.info(f"⬅️ Response status: {response.status_code}") return response @app.get("/", response_class=HTMLResponse) async def home(): template = template_env.get_template("home.html") content = template.render(debug_user=None) return HTMLResponse(content=content) @app.get("/login", response_class=HTMLResponse) async def login_page(): template = template_env.get_template("login.html") content = template.render() return HTMLResponse(content=content) @app.post("/login") async def login(request: Request): data = await request.json() account = data.get("account") password = data.get("password") hash_password = get_password_hash(password) if not account or not password: logger.warning(f"Login failed: missing credentials from {request.client.host}") return JSONResponse( {"success": False, "message": "请输入用户名和密码"}, status_code=400 ) result = await user.check_user(account, hash_password) if not result: logger.warning(f"Login failed: user not found - {account}") return JSONResponse( {"success": False, "message": "用户名或密码错误"}, status_code=401 ) user_id, hashed_password_from_db = result if not verify_password(password, hashed_password_from_db): logger.warning(f"Login failed: wrong password for user {account}") return JSONResponse( {"success": False, "message": "用户名或密码错误"}, status_code=401 ) access_token_expires = timedelta(minutes=int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", 30))) access_token = create_access_token(data={"sub": str(user_id)}, expires_delta=access_token_expires) logger.info(f"🔐 User {user_id} logged in successfully") response = JSONResponse({"success": True, "account": account}) response.set_cookie( key="access_token", value=access_token, httponly=True, secure=False, samesite="lax", max_age=access_token_expires.total_seconds() ) return response @app.get("/user", response_class=HTMLResponse) async def chat_page(request: Request, current_user_id: str = Depends(get_current_user_id)): client_ip = request.client.host logger.info(f"📋 User {current_user_id} accessing /user from IP: {client_ip}") if not current_user_id: logger.warning(f"🚫 Unauthorized access to /user from IP: {client_ip}") return RedirectResponse(url="/login") template = template_env.get_template("ai_talk.html") characters = await character.get_all_characters() characters_json = json.dumps([ {"id": c["id"], "name": c["name"], "trait": c["trait"]} for c in characters ], ensure_ascii=False) content = template.render(characters=characters, characters_json=characters_json, debug_user=current_user_id) return HTMLResponse(content=content) @app.post("/user/chat") async def dashscope_chat( request: Request, current_user_id: str = Depends(get_current_user_id) ): client_ip = request.client.host if not current_user_id: logger.warning(f"🚫 Chat attempt without auth from IP: {client_ip}") return JSONResponse({"error": "未授权访问"}, status_code=401) logger.info(f"💬 User {current_user_id} sending message from {client_ip}") data = await request.json() character_id = data.get("character_id") user_message = data.get("message") if not character_id or not user_message: logger.warning(f"User {current_user_id}: Missing params in chat request - {data}") return JSONResponse({"error": "缺少必要参数"}, status_code=400) characters = await character.get_character_by_id(character_id) if not characters: logger.warning(f"User {current_user_id}: Invalid character ID {character_id}") return JSONResponse({"error": "角色不存在"}, status_code=404) system_prompt = f""" 你正在扮演 {characters['name']}。 人物设定:{characters['trait']} 请始终以这个角色的身份、语气和思维方式回答问题。 不要暴露你是 AI 的事实。 """.strip() try: API_KEY = os.getenv("DASHSCOPE_API_KEY") if not API_KEY: logger.error("❗ DASHSCOPE_API_KEY is not set") return JSONResponse({"error": "API密钥未配置"}, status_code=500) headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", "Accept": "application/json" } payload = { "model": "qwen-plus", "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_message} ], "temperature": 0.85, "top_p": 0.95, "max_tokens": 512, "stream": False } async with httpx.AsyncClient(timeout=30.0) as client: resp = await client.post( "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", json=payload, headers=headers ) if resp.status_code != 200: error_detail = resp.text logger.error(f"☁️ Remote API error [{resp.status_code}]: {error_detail}") return JSONResponse( {"error": f"远程API错误 [{resp.status_code}]", "detail": error_detail}, status_code=resp.status_code ) result = resp.json() reply = result["choices"][0]["message"]["content"].strip() await conversation.save_conversation(int(current_user_id), character_id, user_message, reply) logger.info(f"🤖 Reply generated for user {current_user_id}, length: {len(reply)} chars") return JSONResponse({"reply": reply}) except Exception as e: import traceback error_msg = traceback.format_exc() logger.critical(f"💥 Unexpected error in /user2/chat:\n{error_msg}") return JSONResponse( {"error": f"请求失败: {str(e)}", "detail": str(e)}, status_code=500 ) if __name__ == "__main__": uvicorn.run("myapp:app", host="127.0.0.1", port=8000, reload=True, log_level="info") 现在我要把主程序和api接口分离,不要改变基本的函数调用
最新发布
11-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值