Skip to content

[안승리] Sprint 5#161

Open
Atory0206 wants to merge 7 commits intocodeit-bootcamp-spring:안승리from
Atory0206:sprint5
Open

[안승리] Sprint 5#161
Atory0206 wants to merge 7 commits intocodeit-bootcamp-spring:안승리from
Atory0206:sprint5

Conversation

@Atory0206
Copy link
Copy Markdown
Collaborator

@Atory0206 Atory0206 commented Feb 24, 2026

기본 요구사항

심화 요구사항

  • 다음의 정적 리소스를 서빙하여 프론트엔드와 통합해보세요. API 스펙을 준수했다면 잘 동작할거예요.

fe_1.0.0.zip

화면 가이드

  • Railway.app을 활용하여 애플리케이션을 배포해보세요.

Railway.app은 애플리케이션을 쉽게 배포할 수 있도록 도와주는 PaaS입니다.

  • Railway.app에 가입하고, 배포할 GitHub 레포지토리를 연결하세요.
  • Settings > Network 섹션에서 Generate Domain 버튼을 통해 도메인을 생성하세요.
  • 생성된 도메인에 접속해 배포된 애플리케이션을 테스트해보세요.

스크린샷

image

멘토에게

joonfluence

This comment was marked as spam.

joonfluence

This comment was marked as spam.

Copy link
Copy Markdown
Collaborator

@joonfluence joonfluence left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

총평

Priority Count 의미
P1 4 반드시 수정 (보안/데이터 손실)
P2 7 머지 전 수정 권장 (버그/주요 결함)
P3 5 가능하면 수정 (코드 품질)
P4 4 개선 제안
P5 3 Nitpick

)
})
@PostMapping("/login")
public ResponseEntity<User> login(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 비밀번호 해시 노출

ResponseEntity<User>를 반환하면 User 엔티티의 password 필드가 JSON 응답에 그대로 포함됩니다. OWASP A01:2021 Broken Access Control 해당.

Suggested change
public ResponseEntity<User> login(
public ResponseEntity<UserDto> login(

UserDto 또는 UserLoginResponse DTO로 변환하여 반환하세요. 또는 User.password@JsonIgnore를 추가하세요.


String name = Optional.ofNullable(request.newUsername()).orElse(user.getUsername());
String email = Optional.ofNullable(request.newEmail()).orElse(user.getEmail());
String password = Optional.ofNullable(request.newPassword()).orElse(user.getPassword());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 비밀번호 업데이트 시 해싱 누락 (평문 저장)

create()에서는 passwordEncoder.encode()를 사용하지만, update()에서는 새 비밀번호를 해싱 없이 평문으로 저장합니다. 이후 passwordEncoder.matches()로 로그인 시 항상 실패하게 됩니다.

// Fix:
String password = Optional.ofNullable(request.newPassword())
    .map(passwordEncoder::encode)  // 해싱 추가
    .orElse(user.getPassword());

examples = @ExampleObject(value = "User with email {email} already exists")))
})
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<User> createUser(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] User Entity 직접 반환 — 비밀번호 노출

createUserResponseEntity<User>를 반환하여 password가 응답에 포함됩니다. findAll/findByIdUserDto를 반환하므로 일관성도 없습니다.

UserDto로 통일하세요:

public ResponseEntity<UserDto> createUser(...) {
    User user = userService.create(...);
    return ResponseEntity.status(HttpStatus.CREATED).body(userService.toDto(user));
}

package com.sprint.mission.discodeit.user.dto;

import com.sprint.mission.discodeit.binarycontent.dto.BinaryContentResponse;
import jakarta.validation.constraints.Email;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 유효성 검증 어노테이션 제거됨

기존 @NotBlank, @Email 어노테이션이 모두 제거되었습니다. 빈 문자열, null, 잘못된 이메일이 그대로 저장됩니다.

// Fix:
public record UserCreateRequest(
    @NotBlank String username,
    @NotBlank @Email String email,
    @NotBlank String password
) {}

Controller에 @Valid도 추가 필요.

http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Spring Security 무력화 — 전체 엔드포인트 인증 없음

CSRF 비활성화 + anyRequest().permitAll()로 모든 요청이 허용됩니다. 로그인 엔드포인트가 존재하지만 실질적 인증이 없어 무의미합니다.

개발 단계라면 최소한 // TODO: SECURITY - enable auth before production 주석을 남기거나, 준비가 안 됐다면 spring-boot-starter-security 의존성 자체를 제거하세요.

import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P5] 미사용 import — HttpStatusCode

사용되지 않는 import입니다. 제거하세요.

private ChannelDto toDto(Channel channel) {
Instant lastMessageAt = messageRepository.findByChannelId(channel.getId())
.stream()
.sorted(Comparator.comparing(Message::getCreatedAt).reversed())
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P4] 비효율적인 정렬 패턴

최대값을 구하기 위해 전체 리스트를 정렬(O(n log n))하고 있습니다. Stream.max()를 사용하면 O(n)으로 개선됩니다.

// Fix:
Instant lastMessageAt = messageRepository.findByChannelId(channel.getId())
    .stream()
    .map(Message::getCreatedAt)
    .max(Comparator.naturalOrder())
    .orElse(Instant.MIN);

@PatchMapping(
value = "/{userId}",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<User> updateUser(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] updateUser도 Entity 직접 반환

createUser와 동일하게 ResponseEntity<User>를 반환하여 password가 노출됩니다. UserDto로 변환하세요.

private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;

public User login(UserLoginRequest request) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] AuthService가 User Entity 직접 반환

login() 메서드가 User를 그대로 반환합니다. 서비스 계층에서 DTO로 변환하여 반환하는 것이 바람직합니다.

또한, UserStatusRepository를 import하지만 사용하지 않습니다 (dead import).

@@ -0,0 +1,8 @@
[build]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P4] railway.toml 위치 오류

railway.tomlsrc/main/java/com/sprint/mission/discodeit/ 내부에 있습니다. Railway는 프로젝트 루트에서 이 파일을 찾으므로, 현재 위치에서는 인식되지 않습니다.

프로젝트 루트 디렉토리로 이동하세요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants