사용자가 있는 프로젝트를 하다보니 사용자 ID를 사용했다.
프론트의 응답과 요청에 모두 사용자 ID를 넣어 사용했고 요청에서 사용자 ID는 RequestBody 또는 EndPoint에서 사용했다.
ex) /user/{member-id}
개인 프로젝트 혹은 미니 프로젝트로 연습삼아 했을 땐 괜찮았는데 프론트와 협업을 해보니 문제가 발생했다. 이 사용자 ID를 프론트에선 저장해야 요청에 사용할 수 있어 로컬 스토리지에 저장해놓고 사용했다. 이때 사용자 ID값을 수정해서 다른 사용자 권한을 이용할 수 있었다. 그래서 이 부분을 해결하기 위해 JWT인증을 성공한 사용자의 ID를 authentication으로 만들고 SecurityContextHolder에 넣어 사용하기로 하였다. 이로인해 프론트는 토큰 외에 값은 따로 저장하지 않아도 되고, API도 간단해져 좋은 효과를 보았다. 위 부분이 당연할지 몰라도 막상 문제가 생기고 해결해보니 그 효과를 똑똑히 느낀 문제였다.
private void saveAuthentication(Member member) {
UserDetails userDetails = User.builder()
.username(String.valueOf(member.getMemberId()))
.password("null")
.roles(member.getRole().name())
.build();
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, authoritiesMapper.mapAuthorities(userDetails.getAuthorities()));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
JWT 인증 후 사용자 정보를 넣은 모습, 카카오 로그인만 사용해서 따로 비밀번호는 넣지 않았다.
@Component
public class AuthenticationGetMemberId {
public Long getMemberId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication.getName().equals("anonymousUser") ? 0 : Long.parseLong(authentication.getName());
}
}
컴포넌트로 등록하여 context에 넣은 사용자 ID를 가지고 오는 것으로 만들었다.
anonymousUser가 나온 이유는 JWT로만 인증을 하다보니 게스트용 URL을 통해 요청이 오면 jwt 필터를 통과하게 만들었다. 그러다보니 JWT에 사용자 ID가 포함되어있는데 이 값이 없어 anonymousUser가 된다.