코드 그라데이션

JWT 예제 구현 (10) Response 시 DTO를 통해서만 응답하도록 변경 본문

Spring/Security

JWT 예제 구현 (10) Response 시 DTO를 통해서만 응답하도록 변경

완벽한 장면 2023. 12. 19. 15:03

Controller

UserController

@RequiredArgsConstructor
@RestController
@RequestMapping("/api")
public class UserController {

    private final UserService userService;

    /**
     * 사용자 등록을 처리하는 엔드포인트.
     *
     * @param userDto 등록할 사용자 정보를 포함한 UserDto 객체
     * @return ResponseEntity<UserDto> 등록된 사용자 정보를 포함한 ResponseEntity
     */
     // 여기 변경
    @PostMapping("/signup")
    public ResponseEntity<UserDto> signup(@Valid @RequestBody UserDto userDto) {
        return ResponseEntity.ok(userService.signup(userDto));
    }

    /**
     * 현재 사용자의 정보를 조회하는 엔드포인트.
     *
     * @param request HttpServletRequest 객체
     * @return ResponseEntity<UserDto> 현재 사용자 정보를 포함한 ResponseEntity
     */
     
    // 여기 변경
    @GetMapping("/user")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public ResponseEntity<UserDto> getMyUserInfo(HttpServletRequest request) {
        return ResponseEntity.ok(userService.getMyUserWithAuthorities());
    }

    /**
     * 리디렉션 테스트를 위한 엔드포인트.
     *
     * @param response HttpServletResponse 객체
     * @throws IOException 입출력 예외 발생 시
     */
    @PostMapping("/test-redirect")
    public void testRedirect(HttpServletResponse response) throws IOException {
        response.sendRedirect("/api/user");
    }

    /**
     * 특정 사용자의 정보를 조회하는 엔드포인트.
     *
     * @param username 조회할 사용자의 이름
     * @return ResponseEntity<UserDto> 조회된 사용자 정보를 포함한 ResponseEntity
     */
     // 여기 변경
    @GetMapping("/user/{username}")
    @PreAuthorize("hasAnyRole('ADMIN')")
    public ResponseEntity<UserDto> getUserInfo(@PathVariable String username) {
        return ResponseEntity.ok(userService.getUserWithAuthorities(username));
    }
}

전체적으로 반환형 User -> UserDto

 

 

DTO

AuthorityDto 새로 생성

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AuthorityDto {
   private String authorityName;
}

 

UserDto에 추가

import com.fasterxml.jackson.annotation.JsonProperty;
import inflearn.freejwt.entity.User;
import lombok.*;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Set;
import java.util.stream.Collectors;

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDto {

    @NotNull
    @Size(min = 3, max = 50)
    private String username;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    @NotNull
    @Size(min = 3, max = 100)
    private String password;

    @NotNull
    @Size(min = 3, max = 50)
    private String nickname;


    // 추가: UserDto 클래스에 있는 authorityDtoSet 필드를 선언.
    private Set<AuthorityDto> authorityDtoSet;

    // 정적 메서드인 from(User user)를 정의.
    public static UserDto from(User user) {
        // 만약 입력으로 주어진 user가 null이면 null을 반환.
        if (user == null) return null;

        // UserDto 객체를 빌더 패턴을 사용하여 생성.
        return UserDto.builder()
                // User 객체의 username 값을 UserDto 객체의 username에 설정.
                .username(user.getUsername())
                // User 객체의 nickname 값을 UserDto 객체의 nickname에 설정.
                .nickname(user.getNickname())
                // User 객체의 authorities (권한) 집합을 스트림으로 변환한 후,
                // 각 권한을 AuthorityDto 객체로 매핑하여 새로운 Set으로 수집.
                .authorityDtoSet(user.getAuthorities().stream()
                        .map(authority -> AuthorityDto.builder().authorityName(authority.getAuthorityName()).build())
                        .collect(Collectors.toSet()))
                // UserDto 객체를 빌드하여 반환합니다.
                .build();
    }
}

 

User에 @JsonIgnore 어노테이션 삭제

 

UserService

import inflearn.freejwt.dto.UserDto;
import inflearn.freejwt.entity.Authority;
import inflearn.freejwt.entity.User;
import inflearn.freejwt.exception.DuplicateMemberException;
import inflearn.freejwt.repository.UserRepository;
import inflearn.freejwt.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Optional;

@RequiredArgsConstructor
@Service
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;


    /**
     *
     * @param userDto
     * @return
     */
    @Transactional
    public UserDto signup(UserDto userDto) {
        if (userRepository.findOneWithAuthoritiesByUsername(userDto.getUsername()).orElse(null) != null) {
            throw new DuplicateMemberException("이미 가입되어 있는 유저입니다."); // 변경
        }
        // 권한 정보 생성
        Authority authority = Authority.builder()
                .authorityName("ROLE_USER")
                .build();

        // 유저 정보 생성
        User user = User.builder()
                .username(userDto.getUsername())
                .password(passwordEncoder.encode(userDto.getPassword()))
                .nickname(userDto.getNickname())
                .authorities(Collections.singleton(authority))
                .activated(true)
                .build();

        // 저장
        return UserDto.from(userRepository.save(user));
    }


    /**
     *
     * @param username
     * @return
     */
    @Transactional(readOnly = true)
    public UserDto getUserWithAuthorities(String username) {
        return UserDto.from(userRepository.findOneWithAuthoritiesByUsername(username).orElse(null));
    }

    /**
     *
     * @return
     */
    @Transactional(readOnly = true)
    public UserDto getMyUserWithAuthorities() {
        return UserDto.from(SecurityUtil.getCurrentUsername().flatMap(userRepository::findOneWithAuthoritiesByUsername).orElse(null));
    }

}

 

 

반환형 : Optional<User> -> UserDto

리턴 변경

728x90
Comments