[스파르타코딩클럽]/TIL

[240118] userDetails null 오류

진진리 2024. 1. 18. 23:20
프로젝트를 진행하던 중에 게시글 전체를 조회하는 api에서도 UserDetailsImpl을 통해 사용자 정보를 받아올 필요성이 생겼다.
하지만 해당 api에서 가져온 userDetails가 null값인 오류가 발생하였다.

 

UserDetailsImpl을 추가하게 된 BoardController API 코드

// Best 게시글 조회
@GetMapping("/best")
public String getBestBoards(Model model, @AuthenticationPrincipal UserDetailsImpl userDetails) {
    BoardBestListGetRes bestBoards = boardService.getBoardBestList();
    model.addAttribute("bestBoards", bestBoards);
    model.addAttribute("boardList", bestBoards.getBoards());
    log.info("userId : {}", userDetails.getUser().getId());
    return "mainPage";
}

 

처음에 userDetails에서 받아온 값이 null이라는 얘기를 들었을 때 가장 먼저 떠오른 것은 JwtAuthorizationFilter의 whiteList였다.

전에 TIL을 작성했듯이 쿠키에 값을 가지고 있는 경우에도 인가 필터를 통과할 수 있는 api들의 목록을 whiteList로 만들었기 때문이다.

기존에는 권한을 확인하고 않아도 게시글을 조회할 수 있었기 때문에 이 whiteList에도 "/api/boards/best" url도 등록되어 있었다.

 

따라서 해당 url을 주석처리한 한 후에 다시 테스트를 진행하였다.

 

JwtAuthorizationFilter 코드

    private static final List<RequestMatcher> whiteList =
            List.of(
                    new AntPathRequestMatcher("/api/users/signup", HttpMethod.POST.name()),
                    new AntPathRequestMatcher("/api/users/login", HttpMethod.POST.name()),
//                    new AntPathRequestMatcher("/api/boards/best", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/boards/{boardId}", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/boards/region", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/users/naver/callback/**", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/users/kakao/callback/**", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/**/*.html")
            );

 

이번에는 UserDetails가 null이 아닐 것이라는 예상과 다르게 이번에도 null 값이 나왔다.

그래서 새로 api를 만들어서 userDetails를 잘 받아오는지 테스트를 진행해보았다.

 

"/api/boards"에 해당하는 요청에서는 userDetails를 잘 받아왔는데

"/api/boards/bestone"에서는 userDetails이 null이었다.

"/api/boards/best/one"에서는 userDetails 값을 잘 받아왔다.

 

몇 번의 테스트를 해본 결과 "/api/boards/---" 와 같은 url에 대한 api 요청에서는 모두 userDetails가 null인 것을 알 수 있었다.

그리고 단건 조회에에 해당하는 api 역시 userDetails의 값이 null이었다.

@GetMapping("/{boardId}")
public CommonResponse<BoardGetRes> getBoard(@PathVariable Long boardId, 
    @AuthenticationPrincipal UserDetailsImpl userDetails) {
    log.info("userId : {}", userDetails.getUser().getId());
    return CommonResponse.success(boardService.getBoard(boardId));
}

 

 

그리고 다시 JwtAuthorizationFilter의 whiteList를 보고 혹시나 하는 마음에 주석을 다음과 같이 추가하였다.

    private static final List<RequestMatcher> whiteList =
            List.of(
                    new AntPathRequestMatcher("/api/users/signup", HttpMethod.POST.name()),
                    new AntPathRequestMatcher("/api/users/login", HttpMethod.POST.name()),
//                    new AntPathRequestMatcher("/api/boards/best", HttpMethod.GET.name()),
//                    new AntPathRequestMatcher("/api/boards/{boardId}", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/boards/region", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/users/naver/callback/**", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/users/kakao/callback/**", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/**/*.html")
            );

 

그러자 "/api/boards/best"에 대한 요청에서 userDetails 값을 제대로 받아오는 것을 확인할 수 있었다.

"/api/boards/{boardId}"에서 boardId에 Long 데이터가 들어가는 경우를 생각해서 whiteList에 추가하였으나 String이 들어가도 같은 api로 인식한다는 것을 알 수 있었다.

 

이번 프로젝트에서는 단건 조회의 경우에도 userDetails를 받아오도록 수정할 예정이기 때문에 둘 다 지우는 것으로 해결 가능했다.

 

그렇다면 {userId}에 Long형 값이 들어가는 경우만 whiteList 처리하기 위해서는 어떻게 해야 할까?

찾아보니 정규표현식을 이용하여 api 요청을 표현할 수 있는 RegexRequestMatcher를 사용할 수 있다고 한다.

이를 가지고 whiteList를 수정한다면 다음과 같이 작성하면 된다.

    private static final List<RequestMatcher> whiteList =
            List.of(
                    new AntPathRequestMatcher("/api/users/signup", HttpMethod.POST.name()),
                    new AntPathRequestMatcher("/api/users/login", HttpMethod.POST.name()),
                    new RegexRequestMatcher("api/boards/(\\d+)", HttpMethod.GET.name()), // 추가한 부분
                    new AntPathRequestMatcher("/api/boards/region", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/users/naver/callback/**", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/api/users/kakao/callback/**", HttpMethod.GET.name()),
                    new AntPathRequestMatcher("/**/*.html")
            );