feat: 系統上線前測試代碼清理和功能修復
重大修復: - 修復固定測試用戶 ID,改為從 JWT token 正確解析 - 移除所有 AllowAnonymous 認證繞過,啟用生產級安全保護 - 清理開發專用配置,移除 test-key 允許邏輯 - 修復前端認證 token 發送,統一使用 auth_token key 功能驗證: - ✅ 圖片生成功能完全正常 - ✅ Google Cloud Storage 儲存成功驗證 - ✅ 完整的認證保護已啟用 - ✅ 前後端認證整合完成 系統現已準備好安全上線! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
99677fc014
commit
58b833ef98
|
|
@ -7,7 +7,7 @@ using System.Diagnostics;
|
|||
namespace DramaLing.Api.Controllers;
|
||||
|
||||
[Route("api/ai")]
|
||||
[AllowAnonymous]
|
||||
[Authorize]
|
||||
public class AIController : BaseController
|
||||
{
|
||||
private readonly IAnalysisService _analysisService;
|
||||
|
|
|
|||
|
|
@ -73,12 +73,6 @@ public abstract class BaseController : ControllerBase
|
|||
if (Guid.TryParse(userIdString, out var parsedUserId))
|
||||
return parsedUserId;
|
||||
|
||||
// 開發階段:使用固定測試用戶ID
|
||||
if (IsTestEnvironment())
|
||||
{
|
||||
return Guid.Parse("00000000-0000-0000-0000-000000000001");
|
||||
}
|
||||
|
||||
throw new UnauthorizedAccessException("Invalid or missing user authentication");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
namespace DramaLing.Api.Controllers;
|
||||
|
||||
[Route("api/flashcards")]
|
||||
[AllowAnonymous] // 暫時開放以測試 nextReviewDate 修復
|
||||
[Authorize]
|
||||
public class FlashcardsController : BaseController
|
||||
{
|
||||
private readonly IFlashcardRepository _flashcardRepository;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using System.Security.Claims;
|
|||
namespace DramaLing.Api.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[AllowAnonymous] // 暫時移除認證要求,與 FlashcardsController 保持一致
|
||||
[Authorize]
|
||||
public class ImageGenerationController : BaseController
|
||||
{
|
||||
private readonly IImageGenerationOrchestrator _orchestrator;
|
||||
|
|
@ -156,23 +156,19 @@ public class ImageGenerationController : BaseController
|
|||
|
||||
private Guid GetCurrentUserId()
|
||||
{
|
||||
// 暫時使用固定測試用戶 ID,與 FlashcardsController 保持一致
|
||||
return Guid.Parse("00000000-0000-0000-0000-000000000001");
|
||||
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
?? User.FindFirst("sub")?.Value;
|
||||
|
||||
// TODO: 恢復真實認證後改回 JWT Token 解析
|
||||
// var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
// ?? User.FindFirst("sub")?.Value;
|
||||
//
|
||||
// if (string.IsNullOrEmpty(userIdClaim))
|
||||
// {
|
||||
// throw new UnauthorizedAccessException("User ID not found in token");
|
||||
// }
|
||||
//
|
||||
// if (!Guid.TryParse(userIdClaim, out var userId))
|
||||
// {
|
||||
// throw new UnauthorizedAccessException("Invalid user ID format in token");
|
||||
// }
|
||||
//
|
||||
// return userId;
|
||||
if (string.IsNullOrEmpty(userIdClaim))
|
||||
{
|
||||
throw new UnauthorizedAccessException("User ID not found in token");
|
||||
}
|
||||
|
||||
if (!Guid.TryParse(userIdClaim, out var userId))
|
||||
{
|
||||
throw new UnauthorizedAccessException("Invalid user ID format in token");
|
||||
}
|
||||
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ public class GeminiOptionsValidator : IValidateOptions<GeminiOptions>
|
|||
if (string.IsNullOrWhiteSpace(options.ApiKey))
|
||||
failures.Add("Gemini API key is required");
|
||||
|
||||
if (options.ApiKey?.StartsWith("AIza") != true && options.ApiKey != "test-key")
|
||||
if (options.ApiKey?.StartsWith("AIza") != true)
|
||||
failures.Add("Gemini API key format is invalid (should start with 'AIza')");
|
||||
|
||||
if (options.TimeoutSeconds <= 0 || options.TimeoutSeconds > 120)
|
||||
|
|
|
|||
|
|
@ -41,13 +41,7 @@ if (builder.Environment.IsDevelopment())
|
|||
{
|
||||
options.ApiKey = envApiKey;
|
||||
}
|
||||
// 如果環境變數沒有,Configuration 應該已經包含 user-secrets
|
||||
// 這裡只是作為後備,不應該覆蓋已經從 user-secrets 載入的設定
|
||||
else if (string.IsNullOrEmpty(builder.Configuration["Gemini:ApiKey"]))
|
||||
{
|
||||
// 只有在真的沒有任何配置時才使用測試金鑰
|
||||
options.ApiKey = "test-key";
|
||||
}
|
||||
// 生產環境必須有正確的 API key 配置
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue