新增 token 验证

This commit is contained in:
Wenjie Zhang 2025-04-03 20:45:58 +08:00
parent fbbefe0a63
commit b51b8de460
6 changed files with 102 additions and 51 deletions

View File

@ -23,6 +23,10 @@ class TokenCreate(BaseModel):
agent_id: str
name: str
class TokenVerify(BaseModel):
agent_id: str
token: str
class TokenResponse(BaseModel):
id: int
agent_id: str
@ -80,4 +84,20 @@ async def delete_token(token_id: int, db: Session = Depends(get_db)):
db.delete(token)
db.commit()
return {"success": True, "message": "Token deleted"}
return {"success": True, "message": "Token deleted"}
@admin.post("/verify_token")
async def verify_agent_token(
token_data: TokenVerify,
db: Session = Depends(get_db)
):
"""验证智能体访问令牌"""
token = db.query(AgentToken).filter(
AgentToken.agent_id == token_data.agent_id,
AgentToken.token == token_data.token
).first()
if not token:
raise HTTPException(status_code=401, detail="Invalid token")
return {"success": True, "message": "Token verified"}

View File

@ -6,47 +6,15 @@ import uuid
from fastapi import APIRouter, Body, Depends, HTTPException
from fastapi.responses import StreamingResponse
from langchain_core.messages import AIMessageChunk
from pydantic import BaseModel
from sqlalchemy.orm import Session
from src import executor, config, retriever
from src.core import HistoryManager
from src.agents import agent_manager
from src.models import select_model
from src.utils.logging_config import logger
from src.utils.db_manager import db_manager
from src.models.token_model import AgentToken
chat = APIRouter(prefix="/chat")
# 依赖项:获取数据库会话
def get_db():
db = db_manager.get_session()
try:
yield db
finally:
db.close()
class TokenVerify(BaseModel):
agent_id: str
token: str
@chat.post("/verify_token")
async def verify_agent_token(
token_data: TokenVerify,
db: Session = Depends(get_db)
):
"""验证智能体访问令牌"""
token = db.query(AgentToken).filter(
AgentToken.agent_id == token_data.agent_id,
AgentToken.token == token_data.token
).first()
if not token:
raise HTTPException(status_code=401, detail="Invalid token")
return {"success": True, "message": "Token verified"}
@chat.get("/")
async def chat_get():
return "Chat Get!"

View File

@ -1,9 +1,8 @@
<template>
<div class="token-manager">
<h2 class="manager-title">访问令牌管理</h2>
<div class="token-tools">
<a-button type="primary" size="small" @click="showAddTokenModal">
<PlusOutlined /> 创建令牌
<PlusOutlined /> 创建 Token
</a-button>
</div>
<!-- 令牌列表 -->
@ -190,7 +189,7 @@ onMounted(() => {
<style lang="less" scoped>
.token-manager {
margin-top: 1rem;
padding: 0 0.5rem;
// padding: 0 0.5rem;
}
.manager-title {
@ -207,6 +206,12 @@ onMounted(() => {
.token-list {
max-height: calc(100vh - 400px);
overflow-y: auto;
li.ant-list-item {
background-color: var(--gray-100);
border-radius: 0.5rem;
padding: 0.5rem;
margin-bottom: 0.5rem;
}
}
.token-item {

View File

@ -53,7 +53,7 @@ const router = createRouter({
{
path: '/agent/:agent_id',
name: 'AgentSinglePage',
component: () => import('../components/AgentChatComponent.vue'),
component: () => import('../views/AgentSingleView.vue'),
},
{
path: '/graph',

View File

@ -2,12 +2,13 @@
<div class="agent-single-view">
<!-- Token验证弹窗 -->
<a-modal
v-model:visible="tokenModalVisible"
v-model:open="tokenModalVisible"
title="访问验证"
:closable="false"
:maskClosable="false"
:keyboard="false"
:footer="null"
width="500px"
>
<div class="token-verify-form">
<p>需要输入访问令牌才能使用该智能体</p>
@ -56,7 +57,7 @@ const verifyToken = async () => {
errorMessage.value = '';
try {
const response = await fetch('/api/chat/verify_token', {
const response = await fetch('/api/admin/verify_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -72,8 +73,8 @@ const verifyToken = async () => {
isVerified.value = true;
tokenModalVisible.value = false;
// localStorage
localStorage.setItem(`agent-token-verified-${agentId.value}`, 'true');
// localStorage
localStorage.setItem(`agent-token-${agentId.value}`, tokenInput.value);
} else {
//
const data = await response.json();
@ -88,11 +89,42 @@ const verifyToken = async () => {
};
//
const checkVerification = () => {
const verified = localStorage.getItem(`agent-token-verified-${agentId.value}`);
if (verified === 'true') {
isVerified.value = true;
const checkVerification = async () => {
const savedToken = localStorage.getItem(`agent-token-${agentId.value}`);
if (savedToken) {
// 使
verifying.value = true;
try {
const response = await fetch('/api/admin/verify_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_id: agentId.value,
token: savedToken
})
});
if (response.ok) {
//
isVerified.value = true;
tokenInput.value = savedToken; //
} else {
//
localStorage.removeItem(`agent-token-${agentId.value}`);
tokenModalVisible.value = true;
}
} catch (error) {
console.error('验证令牌出错:', error);
tokenModalVisible.value = true;
} finally {
verifying.value = false;
}
} else {
//
tokenModalVisible.value = true;
}
};
@ -122,7 +154,7 @@ onMounted(() => {
.token-actions {
display: flex;
justify-content: flex-end;
justify-content: space-between;
margin-top: 0.5rem;
}
}

View File

@ -89,11 +89,15 @@
打开智能体配置
</a-button>
<!-- 添加Token管理组件 -->
<div class="token-section">
<TokenManagerComponent :agent-id="selectedAgentId" />
</div>
<!-- 添加令牌管理按钮 -->
<a-button
style="margin-top: 16px;"
type="primary"
block
@click="openTokenModal"
>
访问令牌管理
</a-button>
</div>
<div v-else class="no-agent-selected">
请先选择一个智能体
@ -155,6 +159,17 @@
</a-form>
</div>
</a-modal>
<!-- 令牌管理弹窗 -->
<a-modal
v-model:visible="state.tokenModalVisible"
title="访问令牌管理"
width="650px"
:footer="null"
@cancel="closeTokenModal"
>
<TokenManagerComponent v-if="selectedAgentId" :agent-id="selectedAgentId" />
</a-modal>
</div>
</template>
@ -179,6 +194,7 @@ const state = reactive({
isSidebarOpen: JSON.parse(localStorage.getItem('agent-sidebar-open') || 'true'),
isConfigSidebarOpen: false,
configModalVisible: false,
tokenModalVisible: false,
isEmptyConfig: computed(() =>
!selectedAgentId.value ||
Object.keys(configurableItems.value).length === 0
@ -205,6 +221,16 @@ const closeConfigModal = () => {
state.configModalVisible = false;
};
//
const openTokenModal = () => {
state.tokenModalVisible = true;
};
//
const closeTokenModal = () => {
state.tokenModalVisible = false;
};
//
const loadAgentConfig = () => {
// BUG: