fix(auth): 修复邮件验证服务未配置时可绕过验证的安全漏洞
当邮件验证开启但 emailService 未配置时,原逻辑允许用户绕过验证直接注册。 现在会返回 ErrServiceUnavailable 拒绝注册,确保配置错误不会导致安全问题。 - 在验证码检查前先检查 emailService 是否配置 - 添加日志记录帮助发现配置问题 - 新增单元测试覆盖该场景 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,14 +82,18 @@ func (s *AuthService) RegisterWithVerification(ctx context.Context, email, passw
|
|||||||
|
|
||||||
// 检查是否需要邮件验证
|
// 检查是否需要邮件验证
|
||||||
if s.settingService != nil && s.settingService.IsEmailVerifyEnabled(ctx) {
|
if s.settingService != nil && s.settingService.IsEmailVerifyEnabled(ctx) {
|
||||||
|
// 如果邮件验证已开启但邮件服务未配置,拒绝注册
|
||||||
|
// 这是一个配置错误,不应该允许绕过验证
|
||||||
|
if s.emailService == nil {
|
||||||
|
log.Println("[Auth] Email verification enabled but email service not configured, rejecting registration")
|
||||||
|
return "", nil, ErrServiceUnavailable
|
||||||
|
}
|
||||||
if verifyCode == "" {
|
if verifyCode == "" {
|
||||||
return "", nil, ErrEmailVerifyRequired
|
return "", nil, ErrEmailVerifyRequired
|
||||||
}
|
}
|
||||||
// 验证邮箱验证码
|
// 验证邮箱验证码
|
||||||
if s.emailService != nil {
|
if err := s.emailService.VerifyCode(ctx, email, verifyCode); err != nil {
|
||||||
if err := s.emailService.VerifyCode(ctx, email, verifyCode); err != nil {
|
return "", nil, fmt.Errorf("verify code: %w", err)
|
||||||
return "", nil, fmt.Errorf("verify code: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,13 +113,27 @@ func TestAuthService_Register_Disabled(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, ErrRegDisabled)
|
require.ErrorIs(t, err, ErrRegDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthService_Register_EmailVerifyRequired(t *testing.T) {
|
func TestAuthService_Register_EmailVerifyEnabledButServiceNotConfigured(t *testing.T) {
|
||||||
repo := &userRepoStub{}
|
repo := &userRepoStub{}
|
||||||
|
// 邮件验证开启但 emailCache 为 nil(emailService 未配置)
|
||||||
service := newAuthService(repo, map[string]string{
|
service := newAuthService(repo, map[string]string{
|
||||||
SettingKeyRegistrationEnabled: "true",
|
SettingKeyRegistrationEnabled: "true",
|
||||||
SettingKeyEmailVerifyEnabled: "true",
|
SettingKeyEmailVerifyEnabled: "true",
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
|
// 应返回服务不可用错误,而不是允许绕过验证
|
||||||
|
_, _, err := service.RegisterWithVerification(context.Background(), "user@test.com", "password", "any-code")
|
||||||
|
require.ErrorIs(t, err, ErrServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAuthService_Register_EmailVerifyRequired(t *testing.T) {
|
||||||
|
repo := &userRepoStub{}
|
||||||
|
cache := &emailCacheStub{} // 配置 emailService
|
||||||
|
service := newAuthService(repo, map[string]string{
|
||||||
|
SettingKeyRegistrationEnabled: "true",
|
||||||
|
SettingKeyEmailVerifyEnabled: "true",
|
||||||
|
}, cache)
|
||||||
|
|
||||||
_, _, err := service.RegisterWithVerification(context.Background(), "user@test.com", "password", "")
|
_, _, err := service.RegisterWithVerification(context.Background(), "user@test.com", "password", "")
|
||||||
require.ErrorIs(t, err, ErrEmailVerifyRequired)
|
require.ErrorIs(t, err, ErrEmailVerifyRequired)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user