Conversation
This reverts commit 6bb6db2.
sinsehwan
left a comment
There was a problem hiding this comment.
과제 수행하느라 고생하셨습니다! Spring Security에 대한 전체 흐름 정리를 프로젝트 수행 전에 한 번 해 두면 나중에 프로젝트 수행하실 때 편하실 것 같습니다! 그동안 고생하셨습니다
| SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
| http.authorizeHttpRequests(authorizeRequests -> | ||
| authorizeRequests.requestMatchers("/sns/signup", "/sns/login").permitAll() | ||
| .anyRequest().authenticated()).csrf(csrf -> csrf.disable()); |
There was a problem hiding this comment.
보통 세션 기반 인증과 달리 토큰 기반 인증을 사용할 때 csrf를 비활성화 합니다! 그런데 JWT를 사용할 때 csrf를 diable하는 이유가 뭘까요?
| @Configuration | ||
| @EnableWebSecurity | ||
| @RequiredArgsConstructor | ||
| public class WebConfig { |
There was a problem hiding this comment.
Spring Security를 사용하셨네요! 모듈이 복잡한 편이라서 나중에 인증/인가 전체 흐름 관련해서 파트별로 기능을 정리해두면 좋을 것 같아요~ 해당 부분 템플릿화해두면 초기 프로젝트 진행 시 인증/인가 부분을 빠르게 처리해서 넘겨줄 수 있어서 좋습니다
| ResponseEntity<String> responseEntity = new ResponseEntity<>(deleteCheck, HttpStatus.OK); | ||
| return responseEntity; |
There was a problem hiding this comment.
return ResponseEntity.status(HttpStatus.OK).body(response); 형식으로 한 번에 작성할 수도 있습니다! 그리고 응답의 경우 응답 속성이 하나더라도 DTO 형식으로 반환하면 통일성 관점에서 더 깔끔할 것 같아요! 필드 수정 시에도 더 유연하게 처리 가능합니다!
| @Builder | ||
| public record PostResponse( | ||
| Long id, | ||
| String username, | ||
| String content, | ||
| Integer like, | ||
| LocalDateTime createAt, | ||
| LocalDateTime updateAt | ||
| ) { | ||
| public static PostResponse entityToDto(Posts post) { | ||
| return PostResponse.builder() | ||
| .id(post.getId()) | ||
| .username(post.getUsers().getUsername()) | ||
| .content(post.getContent()) | ||
| .like(post.getLikeit()) | ||
| .createAt(post.getCreateat()) | ||
| .updateAt(post.getUpdateat()) | ||
| .build(); | ||
| } | ||
| } |
There was a problem hiding this comment.
빌더의 경우 필요한 파라미터만 유연하게 넣어서 구성할 때 이점이 있는데, 여기서는 항상 모든 필드를 채우는 형식이라서 @Builder보다는 record에서 제공하는 생성자를 써도 될 것 같아요!
|
|
||
| public interface PostRepository extends JpaRepository<Posts, Long> { | ||
| public List<Posts> findAll(); | ||
| public Optional<Posts> findById(Integer id); |
| public List<Posts> findAll(); | ||
| public Optional<Posts> findById(Integer id); | ||
| public List<Posts> findByUsers(Users user); | ||
| public List<Posts> findByContentContaining(String partialContent); |
There was a problem hiding this comment.
검색 특성상 어쩔 수 없긴 한데 %Like% 형식으로 쿼리가 진행될 것 같네요! %Like나 %Like%는 인덱스를 적용하더라도 이점을 누리기 어렵다는 것 정도만 체크 하시면 될 것 같아요! 지금은 구조는 변경하지 않아도 될 것 같습니다
| List<PostResponse> postResponses = new ArrayList<>(); | ||
| for (Posts post : posts) { | ||
| postResponses.add(entityToDto(post)); | ||
| } | ||
| return postResponses; |
There was a problem hiding this comment.
DTO로 변환해서 제공하네요! 좋습니다. 만약 이 부분을 조금 더 깔끔하게 개선해보고 싶으시다면 일급 컬렉션 객체에 대해 알아보시면 더 좋을 거 같아요!
| public boolean validateToken(String token) { | ||
| try { | ||
| parseToken(token); | ||
| return true; | ||
| } catch(JwtException e) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| public String getUserID(String token) { | ||
| Key key = Keys.hmacShaKeyFor(secretKey.getBytes()); | ||
| Claims claims = parseToken(token).getBody(); | ||
| return claims.get("loginID", String.class); | ||
| } | ||
|
|
||
| public Role getRole(String token) { | ||
| Claims claims = parseToken(token).getBody(); | ||
| return Role.valueOf(claims.get("role", String.class)); | ||
| } | ||
| } |
| replyRepository.deleteAll(); | ||
| postRepository.deleteAll(); | ||
| userRepository.deleteAll(); | ||
|
|
||
| Users user1 = Users.builder() | ||
| .age(28) | ||
| .username("Java") | ||
| .build(); | ||
|
|
||
| userRepository.save(user1); | ||
|
|
||
| Users user2 = Users.builder() | ||
| .age(57) | ||
| .username("Unix") | ||
| .build(); | ||
| userRepository.save(user2); | ||
|
|
||
| Posts post = Posts.builder() | ||
| .content("Hello, Java!") | ||
| .users(user1) | ||
| .build(); |
There was a problem hiding this comment.
테스트 코드 좋습니다! 이건 취향차이긴 한데 테스트를 위한 객체를 만들기 위해 Test 폴더 쪽에 TestUtil을 따로 구성해서 객체 생성 로직을 이쪽에 위임해도 됩니다!
변경점 👍
회원가입으로 User 정보를 데이터베이스에 기록하는 endpoint를 생성했으며, User에 권한을 부여하고 User 정보를 명시하는 jwt Token을 만들어 이를 login시에 client에게 전달하였습니다.
버그 해결 💊
Spring Security를 사용할 때 /signup(회원가입 url)에 요청을 보낼 때 이전과 달리 401 Error가 발생하는 현상이 나타났는데, WebConfig에 securityFilterChain 함수를 만들어
테스트 💻
Postman에 등록하려는 사용자 정보를 JSON에 담아 전송하여 회원가입 과정을 완료하고, 로그인 과정도 이와 동일하게 loginID와 password를 담아 진행하여 JWT Token을 서버로부터 받아 사용하였습니다.
스크린샷 🖼
비고 ✏
signup과 login 과정에서 JWT token을 받는 과정만 완료하고, 이를 통해 다른 작업에서 로그인 상태임을 확인하는 것은 보여드리지 못해 아쉽습니다. 다음 스터디까지 JWT를 테스트하고 완료한 다음 배포 과정까지 진행해보도록 하겠습니다!