@@ -55,6 +87,16 @@
diff --git a/main.go b/main.go
index 098568e..d02e51e 100644
--- a/main.go
+++ b/main.go
@@ -73,6 +73,7 @@ func main() {
// API 엔드포인트
mux.HandleFunc("/api/users", handleUsers)
mux.HandleFunc("/api/users/", handleDeleteUser) // DELETE 요청 처리
+ mux.HandleFunc("/api/login", handleLogin) // 로그인 요청 처리
log.Printf("VaultKeeper 서버가 %d 포트에서 시작됩니다.\n", appPort)
log.Printf("HTPASSWD_PATH: %s\n", htpasswdPath)
@@ -217,3 +218,45 @@ func handleDeleteUser(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"message": fmt.Sprintf("사용자 '%s'가 성공적으로 삭제되었습니다.", username)})
}
+
+// handleLogin은 사용자 로그인을 처리합니다.
+func handleLogin(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ http.Error(w, "허용되지 않는 메소드입니다.", http.StatusMethodNotAllowed)
+ return
+ }
+
+ var req LoginRequest
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ http.Error(w, "유효하지 않은 요청 본문입니다.", http.StatusBadRequest)
+ return
+ }
+
+ // 사용자 이름 유효성 검사 (로그인도 동일하게 적용)
+ if !usernameRegex.MatchString(req.Username) {
+ http.Error(w, "유효하지 않은 사용자 이름 형식입니다.", http.StatusBadRequest)
+ return
+ }
+ if req.Username == "" || req.Password == "" {
+ http.Error(w, "사용자 이름과 비밀번호는 필수입니다.", http.StatusBadRequest)
+ return
+ }
+
+ htpasswdMutex.Lock()
+ defer htpasswdMutex.Unlock()
+
+ // htpasswd -v
명령어를 사용하여 비밀번호 확인
+ // exit code 0이면 성공, 0이 아니면 실패
+ cmd := exec.Command("htpasswd", "-v", htpasswdPath, req.Username, req.Password)
+ output, err := cmd.CombinedOutput()
+
+ if err != nil {
+ // htpasswd -v는 비밀번호가 일치하지 않거나 사용자 이름을 찾을 수 없으면 에러를 반환합니다.
+ log.Printf("Login verification failed for user '%s': %v, Output: %s", req.Username, err, output)
+ http.Error(w, "사용자 이름 또는 비밀번호가 올바르지 않습니다.", http.StatusUnauthorized)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(map[string]string{"message": "로그인 성공"})
+}