fix(security): /uploads 目录路径遍历防护

- 替换 Static 为受控文件服务 handler (serveUploads)
- 添加 filepath.Clean 路径清理 + .. 检测
- 使用 Abs + HasPrefix 限制访问范围在上传目录内
- 添加安全响应头(CSP default-src 'none', X-Content-Type-Options nosniff)
This commit is contained in:
2026-05-08 12:28:03 +08:00
parent e49865df11
commit 61692e4c1a
4 changed files with 60 additions and 8 deletions

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/url"
"time"
"github.com/user-management-system/internal/auth/providers"
)
@@ -71,6 +72,9 @@ type OAuthManager interface {
// ValidateToken 验证令牌
ValidateToken(token string) (bool, error)
// ValidateTokenWithProvider 通过指定 provider 验证令牌
ValidateTokenWithProvider(ctx context.Context, provider OAuthProvider, token string) (bool, error)
// GetConfig 获取OAuth配置
GetConfig(provider OAuthProvider) (*OAuthConfig, bool)
@@ -442,9 +446,11 @@ func (m *DefaultOAuthManager) ValidateToken(token string) (bool, error) {
if len(providers) == 0 {
return false, errors.New("no OAuth providers configured")
}
// 添加 5 秒超时,防止 provider API 无响应导致阻塞
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 尝试任一 provider 的 userinfo 端点验证
tokenObj := &OAuthToken{AccessToken: token}
ctx := context.Background()
for _, p := range providers {
if _, err := m.GetUserInfo(ctx, p.Provider, tokenObj); err == nil {
return true, nil
@@ -454,10 +460,13 @@ func (m *DefaultOAuthManager) ValidateToken(token string) (bool, error) {
}
// ValidateTokenWithProvider 通过指定 provider 验证令牌
func (m *DefaultOAuthManager) ValidateTokenWithProvider(provider OAuthProvider, token string) (bool, error) {
func (m *DefaultOAuthManager) ValidateTokenWithProvider(ctx context.Context, provider OAuthProvider, token string) (bool, error) {
if token == "" {
return false, nil
}
if ctx == nil {
ctx = context.Background()
}
cfg, ok := m.GetConfig(provider)
if !ok || cfg.ClientID == "" {
@@ -466,7 +475,6 @@ func (m *DefaultOAuthManager) ValidateTokenWithProvider(provider OAuthProvider,
// 通过 provider 的 userinfo 端点验证 token
tokenObj := &OAuthToken{AccessToken: token}
ctx := context.Background()
_, err := m.GetUserInfo(ctx, provider, tokenObj)
if err != nil {
return false, err