fix(tts): require authentication for TTS endpoints (#1101)
Move TTS routes behind auth middleware and attach JWT to local proxy requests from the frontend. Previously both /api/hermes/tts and /api/tts/proxy/audio/speech were publicly accessible without authentication, allowing unauthenticated callers to consume Edge TTS resources through the server. Changes: - server: move ttsRoutes from public to protected route section - client: auto-attach JWT when baseUrl is a local path (/...) and no external API key is configured - client: import getApiKey() instead of raw localStorage access
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { ref, computed, onUnmounted } from 'vue'
|
import { ref, computed, onUnmounted } from 'vue'
|
||||||
import { generateSpeech, playAudioBlob } from '@/api/hermes/tts'
|
import { generateSpeech, playAudioBlob } from '@/api/hermes/tts'
|
||||||
|
import { getApiKey } from '@/api/client'
|
||||||
|
|
||||||
export interface SpeechOptions {
|
export interface SpeechOptions {
|
||||||
lang?: string // 语言 'zh-CN', 'en-US' 等
|
lang?: string // 语言 'zh-CN', 'en-US' 等
|
||||||
@@ -286,6 +287,10 @@ export function useSpeech() {
|
|||||||
}
|
}
|
||||||
if (opts.apiKey) {
|
if (opts.apiKey) {
|
||||||
headers['Authorization'] = `Bearer ${opts.apiKey}`
|
headers['Authorization'] = `Bearer ${opts.apiKey}`
|
||||||
|
} else if (opts.baseUrl.startsWith('/')) {
|
||||||
|
// 本地代理请求自动附加 JWT
|
||||||
|
const jwt = getApiKey()
|
||||||
|
if (jwt) headers['Authorization'] = `Bearer ${jwt}`
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ export function registerRoutes(app: any, authMiddleware: Array<(ctx: Context, ne
|
|||||||
app.use(healthRoutes.routes())
|
app.use(healthRoutes.routes())
|
||||||
app.use(webhookRoutes.routes())
|
app.use(webhookRoutes.routes())
|
||||||
app.use(authPublicRoutes.routes())
|
app.use(authPublicRoutes.routes())
|
||||||
app.use(ttsRoutes.routes()) // TTS proxy/generation — must be before auth
|
|
||||||
|
|
||||||
// --- Auth middleware: all routes below require authentication ---
|
// --- Auth middleware: all routes below require authentication ---
|
||||||
authMiddleware.forEach((middleware) => app.use(middleware))
|
authMiddleware.forEach((middleware) => app.use(middleware))
|
||||||
|
|
||||||
// --- Protected routes (auth required) ---
|
// --- Protected routes (auth required) ---
|
||||||
app.use(authProtectedRoutes.routes())
|
app.use(authProtectedRoutes.routes())
|
||||||
|
app.use(ttsRoutes.routes())
|
||||||
app.use(uploadRoutes.routes())
|
app.use(uploadRoutes.routes())
|
||||||
app.use(updateRoutes.routes()) // Must be before proxy (proxy catch-all matches everything)
|
app.use(updateRoutes.routes()) // Must be before proxy (proxy catch-all matches everything)
|
||||||
app.use(sessionRoutes.routes())
|
app.use(sessionRoutes.routes())
|
||||||
|
|||||||
Reference in New Issue
Block a user