fix: 보안·안정성·동시성 개선 3차
All checks were successful
Server CI/CD / deploy (push) Successful in 1m31s

- 입력 검증 강화 (로그인/체인 핸들러 전체)
- boss raid 비관적 잠금으로 동시성 문제 해결
- SSAFY 사용자명 sanitize + 트랜잭션 처리
- constant-time API 키 비교, 보안 헤더, graceful shutdown
- 안전하지 않은 기본값 경고 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 21:40:06 +09:00
parent cc751653c4
commit d597ef2d46
11 changed files with 247 additions and 97 deletions

View File

@@ -1,12 +1,16 @@
package auth
import (
"regexp"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
)
// usernameRe allows alphanumeric, underscore, hyphen (3-50 chars).
var usernameRe = regexp.MustCompile(`^[a-z0-9_-]{3,50}$`)
type Handler struct {
svc *Service
}
@@ -27,12 +31,15 @@ func (h *Handler) Register(c *fiber.Ctx) error {
if req.Username == "" || req.Password == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "아이디와 비밀번호를 입력해주세요"})
}
if len(req.Username) > 50 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "아이디는 50자 이하여야 합니다"})
if !usernameRe.MatchString(req.Username) {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "아이디는 3~50자의 영문 소문자, 숫자, _, -만 사용 가능합니다"})
}
if len(req.Password) < 6 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "비밀번호는 6자 이상이어야 합니다"})
}
if len(req.Password) > 72 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "비밀번호는 72자 이하여야 합니다"})
}
if err := h.svc.Register(req.Username, req.Password); err != nil {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": err.Error()})
}
@@ -51,6 +58,12 @@ func (h *Handler) Login(c *fiber.Ctx) error {
if req.Username == "" || req.Password == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "아이디와 비밀번호를 입력해주세요"})
}
if len(req.Username) > 50 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "아이디 또는 비밀번호가 올바르지 않습니다"})
}
if len(req.Password) > 72 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "아이디 또는 비밀번호가 올바르지 않습니다"})
}
accessToken, refreshToken, user, err := h.svc.Login(req.Username, req.Password)
if err != nil {