60 lines
2.6 KiB
Go
60 lines
2.6 KiB
Go
package auth
|
||
|
||
import (
|
||
"context"
|
||
"crypto/sha256"
|
||
"encoding/hex"
|
||
"log/slog"
|
||
"strings"
|
||
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/idgen"
|
||
"hyapp/pkg/logx"
|
||
authdomain "hyapp/services/user-service/internal/domain/auth"
|
||
)
|
||
|
||
const (
|
||
riskBlockReasonIPAsync = "ip_async"
|
||
)
|
||
|
||
func (s *Service) enqueueLoginIPRiskJob(ctx context.Context, meta Meta, token authdomain.Token, channel string, platform string, language string, timezone string) {
|
||
if s.authRepository == nil || strings.TrimSpace(meta.ClientIP) == "" || token.SessionID == "" || token.UserID <= 0 {
|
||
// 没有可复核 IP 或 session 时不创建任务;登录主链路不因此失败。
|
||
return
|
||
}
|
||
nowMs := s.now().UnixMilli()
|
||
clientIP := strings.TrimSpace(meta.ClientIP)
|
||
job := authdomain.LoginIPRiskJob{
|
||
AppCode: appcode.Normalize(token.AppCode),
|
||
JobID: idgen.New("iprisk"),
|
||
SessionID: token.SessionID,
|
||
UserID: token.UserID,
|
||
ClientIP: clientIP,
|
||
ClientIPHash: HashLoginRiskIP(clientIP),
|
||
Channel: normalizeChannel(channel),
|
||
Platform: normalizePlatform(firstNonEmpty(platform, meta.Platform)),
|
||
Language: strings.TrimSpace(firstNonEmpty(language, meta.Language)),
|
||
Timezone: strings.TrimSpace(firstNonEmpty(timezone, meta.Timezone)),
|
||
RequestID: meta.RequestID,
|
||
EdgeCountryCode: normalizeCountryCode(meta.CountryByIP),
|
||
Status: authdomain.LoginIPRiskStatusPending,
|
||
CreatedAtMs: nowMs,
|
||
UpdatedAtMs: nowMs,
|
||
}
|
||
if job.Channel == "" {
|
||
job.Channel = "account"
|
||
}
|
||
if err := s.authRepository.CreateLoginIPRiskJob(ctx, job); err != nil {
|
||
// 风控任务失败按文档 fail-open;日志只输出 IP hash,明文 IP 已在业务表审计。
|
||
logx.Error(logx.With(ctx, slog.String("request_id", meta.RequestID), slog.String("app_code", job.AppCode)), "login_ip_risk_job_create_failed", err, slog.String("component", "user_auth"), slog.String("client_ip_hash", job.ClientIPHash), slog.String("session_id", job.SessionID))
|
||
return
|
||
}
|
||
logx.Info(logx.With(ctx, slog.String("request_id", meta.RequestID), slog.String("app_code", job.AppCode)), "login_ip_risk_job_created", slog.String("component", "user_auth"), slog.String("job_id", job.JobID), slog.String("session_id", job.SessionID), slog.Int64("user_id", job.UserID), slog.String("client_ip_hash", job.ClientIPHash), slog.String("channel", job.Channel), slog.String("platform", job.Platform))
|
||
}
|
||
|
||
// HashLoginRiskIP 生成登录风险 Redis key 和 DB 索引用的稳定 IP 摘要。
|
||
func HashLoginRiskIP(ip string) string {
|
||
sum := sha256.Sum256([]byte(strings.TrimSpace(ip)))
|
||
return hex.EncodeToString(sum[:])
|
||
}
|