Spring boot/위니아에이드 클론코딩 프로젝트

[위니아에이드] 팀 프로젝트 - 쿠키를 이용한 아이디 저장

코딩딩코 2022. 10. 27.

아이디 저장을 선택하고 로그인을 한다면 다음 로그인부터는 아이디를 입력해준 상태로

사용자에게 입력을 받아야 합니다.

저는 쿠키를 이용해서 아이디를 저장해주고 로그인 화면에 쿠키에 값이 있는지 확인 후

데이터를 응답해주는 방식을 사용했습니다.

 

 

function saveIdAndSignin() {
    const loginForm = document.querySelector(".login-form");
    const saveIdInputFlag = saveIdCheckBox.checked;

    $.ajax({
        async: false,
        type: "post",
        url: "/api/v1/auth/save/user-id",
        contentType: "application/json",
        data: JSON.stringify({
            "saveIdInputFlag": saveIdInputFlag,
            "userId": userIdInput.value
        }),
        dataType: "json",
        success: (response) => {
            
        },
        error: errorMessage
    });
    
    loginForm.submit();
}

로그인을 위한 JavaScript 코드입니다.

먼저 Ajax를 통해 아이디 저장Flag와 아이디 값을 데이터로 보내줍니다.

@Log
@PostMapping("/save/user-id")
public ResponseEntity<?> signupUser(@RequestBody Map<String, Object> parametersMap, HttpServletRequest request, HttpServletResponse response) {
    try {
        if((Boolean) parametersMap.get("saveIdInputFlag")) {
        	// 아이디 저장 checkBox가 true면 쿠키 저장
            saveUserIdToCookie((String)parametersMap.get("userId"), response);

        }else {
        	// 아이디 저장 checkBox가 false면 쿠키의 수명을 0으로 해서 삭제
            removeCookie(response);
            
        }
    } catch (Exception e) {
        e.printStackTrace();
        return ResponseEntity.ok(new CustomResponseDto<>(1, "Failed to save to ID cookie", false));
    }

    return ResponseEntity.ok(new CustomResponseDto<>(1, "Saved in ID cookie successfully", true));
}


private void saveUserIdToCookie(String userId, HttpServletResponse response) throws Exception {
        Cookie cookie = new Cookie("userId", userId);
        cookie.setPath("/api/v1/auth/user-id");	// 아이디 정보를 가져오는 API에서만 쿠키 데이터를 읽을 수 있게 설정합니다.
        cookie.setMaxAge(60 * 60 * 24);
        response.addCookie(cookie);
}


private void removeCookie(HttpServletResponse response) throws Exception {
    Cookie cookie = new Cookie("userId", null);
    cookie.setPath("/api/v1/auth/user-id");
    cookie.setMaxAge(0);
    response.addCookie(cookie);
}

Map을 이용해서 매개변수를 받았는데 Dto를 따로 만들어서 받아도 될 것 같습니다.

아이디 저장을 체크하고 로그인 요청을 보내면 쿠키를 생성해주고

아니라면 쿠키의 생명을 0으로 설정해서 쿠키를 제거해줍니다.

그리고 Path를 쿠키 값을 확인하는 요청 주소에서만 읽을 수 있게끔 경로를 따로 잡아 주었습니다.

기본값은 쿠키를 생성한 주소입니다.

checkCookieAndLoadUserId();

function checkCookieAndLoadUserId() {
    $.ajax({
        async: false,
        type: "get",
        url: "/api/v1/auth/user-id",
        datatType: "json",
        success: (response) => {
            if(response.data != null) {
                setUserId(response.data);
                saveIdCheckBox.setAttribute("checked", true);
            }
        },
        error: errorMessage
    });
}

로그인 뷰를 요청하면 제일 먼저 userId 라는 key값을 가진 쿠키를 확인을 하기 위한 코드입니다.

@Log
@GetMapping("/user-id")
public ResponseEntity<?> getUserId(HttpServletRequest request) {
    String userId = null;

    try {
        userId = getUserIdInCookie(request);
    } catch (Exception e) {
        e.printStackTrace();
        return ResponseEntity.internalServerError().body(new CustomResponseDto<>(-1, "Failed to load ID", userId));
    }

    return ResponseEntity.ok(new CustomResponseDto<>(1, "Successfully loaded ID", userId));
}

private String getUserIdInCookie(HttpServletRequest request) throws Exception {

    List<String> cookieValueList = Arrays.stream(request.getCookies()) // Stream 생성
            .filter(cookie -> cookie.getName().equals("userId"))
            .map(Cookie::getValue)
            .collect(Collectors.toList());

    return cookieValueList.isEmpty() ? null : cookieValueList.get(0);
}

여기서도 Stream을 사용을 했습니다.

request.getCookies()는 Cookie[]로 배열을 반환하기 때문에 .stream()이 아닌 다른 방식으로 Stream을 생성해줍니다.

생성하고 filter를 통해서 userId라는 키값을 가진 쿠키를 찾아내고 찾았다면 value를 뽑아서 List로 반환해 주고

결과 값은 어차피 1개이거나 0개이기 때문에 마지막에 삼항연산자를 통해서 null이거나 String 값이 반환됩니다.

 

 

처음에는 FormLogin이 실행되기전에 Filter를 통해서 아이디 체크 Input태그를 확인하고 쿠키에 저장하는 로직으로

진행하려 했지만 FormLogin은 Filter에서 잡아주지 못해서 로그인 버튼 타입을 submit으로 하지 않고 button으로 하고

button에 onclick 이벤트를 주어서 처리하는 로직으로 만들었습니다.

Filter가 FormLogin을 잡아주지 못하는 이유에 대해서는 아직 공부가 더 필요한 것 같습니다.

댓글