#06 로그인한 사용자 구하기

김대진·2023년 4월 10일
0

MyMemory Project

목록 보기
7/9
post-thumbnail

SecurityContextHolder를 사용하여 프론트에서 사용자 정보를 받지 않고도 사용자를 가져올 수 있다.

예를 들어, 게시판 사이트를 운영하는데 내가(id=2) 쓴 글만 보고 싶어 서버에 데이터를 요청할 때 /posts/list/2 와 같이 userId를 같이 보내야 한다면 타인이 접근할 수도 있다는 문제가 있다.

하지만, SecurityContextHolder를 사용한다면 로그인한 사용자의 데이터를 서버 자체적으로 받아올 수 있다.

이전 글에서 토큰을 통한 데이터 요청을 다루었는데, JwtAuthenticationFilter에서 SecurityContextHolder에 유저 정보를 저장하였다.

JwtAuthenticationFilter.class

@RequiredArgsConstructor
public class JwtAuthenticationFilter extends GenericFilterBean {
    private final JwtTokenProvider jwtTokenProvider;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 헤더에서 토큰 받아오기
        String token = jwtTokenProvider.resolveToken((HttpServletRequest) request);

        // 토큰이 유효하다면
        if (token != null && jwtTokenProvider.validateToken(token)) {
            // 토큰으로부터 유저 정보를 받아
            Authentication authentication = jwtTokenProvider.getAuthentication(token);
            // SecurityContext 에 객체 저장
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }
}

SecurityContextHolder에 저장된 유저 정보를 사용하여 로그인한 유저를 구하는 함수를 작성해 보자.

01. U.class

우리 프로젝트에는 common 패키지 안에 U라는 클래스가 존재한다.

U.class의 코드는 다음과 같다.

public class U {
    // 현재 request 구하기
    public static HttpServletRequest getRequest() {
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        return attrs.getRequest();
    }

    // 현재 session 구하기
    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    // 현재 로그인한 사용자 UserDetail 구하기
    public static User getLoggedUser() {
        // 현재 로그인한 유저 정보
        UserDetails userDetails = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return (User) userDetails;
    }
}

getLoggedUser 함수를 보면, SecurityContextHolder의 유저정보를 UserDetail에 담고, 다시 User에 담아 반환한다.

이제 사용방법에 대해 알아보자.

02. 사용방법

예시로, 해당 달의 자신이 쓴 일기 리스트를 반환하는 함수를 보여 주겠다.

MemoService.class

public List<Memo> getMemoList(Integer year, Integer month) {
    Long userId = getUserId();
    LocalDate firstDate = LocalDate.of(year, month, 1);
    LocalDate lastDate = firstDate.withDayOfMonth(firstDate.lengthOfMonth());

    List<Memo> memoList = memoRepository.findByUserIdAndDateBetween(userId, firstDate, lastDate);
    return memoList;
}

userId를 함수 인자가 아닌, getUserId()를 통해 받아오고 있다.

getUserId 함수는 다음과 같다.

private Long getUserId() {
    Long userId = U.getLoggedUser().getId();
    if (userId == null) throw new MyMemoryException(404, "잘못된 유저입니다.");
    userRepository.findById(userId).orElseThrow(() -> {
        return new MyMemoryException(404, "올바르지 않은 유저입니다.");
    });
    return userId;
}

첫 줄을 보면, U.getLoggedUser를 통해 유저를 받아오고 있다.

이러한 방식을 통해

  1. 토큰 복호화
  2. 서버의 SecurityContextHolder 에 유저정보 저장
  3. U.getLoggedUser로 로그인 한 유저 정보 가져오기

단계로 사용자 정보를 가져올 수 있게 된다.

profile
만재 개발자

0개의 댓글