// Instagram.domain.member.controller
@Slf4j
@Api(tags = "멤버 인증 API")
@Validated
@RestController
@RequiredArgsConstructor
public class MemberAuthController {
private final MemberAuthService memberAuthService;
private final int REFRESH_TOKEN_EXPIRES = 60 * 60 * 24 * 7; // 7일
@ApiOperation(value = "username 중복 조회")
@ApiResponses({
@ApiResponse(code = 200, message = "M011 - 사용가능한 username 입니다.\n"
+ "M012 - 사용불가능한 username 입니다."),
@ApiResponse(code = 400, message = "G003 - 유효하지 않은 입력입니다.\n"
+ "G004 - 입력 타입이 유효하지 않습니다.")
})
@ApiImplicitParam(name = "username", value = "유저네임", required = true, example = "dlwlrma")
@GetMapping(value = "/accounts/check")
public ResponseEntity<ResultResponse> checkUsername(
@RequestParam
@Length(min = 4, max = 12, message = "사용자 이름은 4문자 이상 12문자 이하여야 합니다")
@Pattern(regexp = "^[0-9a-zA-Z]+$", message = "username엔 대소문자, 숫자만 사용할 수 있습니다.")
String username) {
final boolean check = memberAuthService.checkUsername(username);
if (check) {
return ResponseEntity.ok(ResultResponse.of(CHECK_USERNAME_GOOD, true));
} else {
return ResponseEntity.ok(ResultResponse.of(CHECK_USERNAME_BAD, false));
}
}
@ApiOperation(value = "회원가입")
@ApiResponses({
@ApiResponse(code = 200, message = "M001 - 회원가입에 성공하였습니다.\n"
+ "M013 - 이메일 인증을 완료할 수 없습니다."),
@ApiResponse(code = 400, message = "G003 - 유효하지 않은 입력입니다.\n"
+ "G004 - 입력 타입이 유효하지 않습니다.\n"
+ "M002 - 이미 존재하는 사용자 이름입니다.\n"
+ "M007 - 인증 이메일 전송을 먼저 해야합니다.")
})
@PostMapping(value = "/accounts")
public ResponseEntity<ResultResponse> register(@Valid @RequestBody RegisterRequest registerRequest) {
final boolean isRegistered = memberAuthService.register(registerRequest);
if (isRegistered) {
return ResponseEntity.ok(ResultResponse.of(REGISTER_SUCCESS, true));
} else {
return ResponseEntity.ok(ResultResponse.of(CONFIRM_EMAIL_FAIL, false));
}
}
@ApiOperation(value = "로그인")
@ApiResponses({
@ApiResponse(code = 200, message = "M002 - 로그인에 성공하였습니다."),
@ApiResponse(code = 400, message = "G003 - 유효하지 않은 입력입니다.\n"
+ "G004 - 입력 타입이 유효하지 않습니다."),
@ApiResponse(code = 401, message = "M005 - 계정 정보가 일치하지 않습니다.")
})
@PostMapping(value = "/login")
public ResponseEntity<ResultResponse> login(@Valid @RequestBody LoginRequest loginRequest) {
throw new FilterMustRespondException();
}
...
}
login 로직이 가장 궁금해서 controller를 설레는마음으로 봤는데 로그인 로직이 throw exception 밖에 안되어있어서 뭐지? 싶었습니다. 제가 이 프로젝트 구성을 이해를 못했거나 보안상문제로 공개하지 않는다로 판단했는데 도저히 모르겠어서 프로젝트 담당자에게 메일을 보냈습니다. 이런 허접한 질문을 해도 답 해주실까...? 걱정했었는데 굉장히 친절히 답해주셨습니다 ㅠㅠ 감동.
저희가 인증/인가 기능을 Spring Security로 구현했다 보니, 가능한 이 프레임워크에 맞게 기능을 구현하려고 개선작업을 했었어요. (기존에는 login 메소드에 로그인 기능을 직접 구현했었어요.)
global.config.security.filter 패키지에 CustomUsernamePasswordAuthenticationFilter 클래스가 있는데, 여기서 attemptAuthentication 메소드를 보시면, /login 요청에 대해 처리하는 로직이 담겨 있구요, 요청 데이터를 객체로 변환하고 부모(AbstractAuthenticationProcessingFilter)의 기능을 그대로 사용하는 방식으로 구현되어 있어요.
로그인부분은 보안상 중요하다보니 따로 빼놓고 관리를 하신듯 합니다. 지금도 저 filter를 시작으로 로그인 로직을 분석중인데 이게 버전 문제도 있고 워낙 설정할게 많다보니 공부하기가 쉽진 않습니다. 이제서야 한 40%정도 이해한거 같아요.
아무튼 각설하고, 로그인은 제쳐둔채 중요한것들만 좀 분석해보겠습니다.
- @Slf4j
로그를 출력하기 위해 사용
- 그 유명한 Log4j와 차이가 뭐지?
Apache 소프트웨어 재단에서 개발한 자바 로깅 프레임워크. 로깅 레벨, 로그 출력 대상 등을 설정할 수 있어서 로깅을 더욱 세밀하게 제어할 수 있습니다.
- 그 유명한 Log4j와 차이가 뭐지?
- @Api
API의 정보를 설명하기 위해 사용되는 애노테이션 - @Validated
유효성 검사 애노테이션, @NotNull 등의 표준 애노테이션뿐만 아니라, @Email이나 @NotEmpty 등의 스프링에서 제공하는 유효성 검사 애노테이션도 사용할 수 있습니다. - @RestController
HTTP 요청과 응답을 처리하고 RESTful 웹 서비스를 구축 - @Value
${} 형태의 SpEL(Sptring Expression Language)을 지원합니다. 따라서, application.properties 파일에서 설정된 값으로 대체됩니다. - @ApiOperation
API 문서화 도구에서 API 작업의 설명을 정의하는 데 사용되는 애노테이션 - @ApiImplicitParam
@ApiOperation과 함께 사용되는 애노테이션 중 하나로, API에서 사용되는 매개 변수에 대한 설명을 정의하는 데 사용 - @Pattern
입력값이 정규표현식 패턴과 일치하는지 검증하는 데 사용되는 스프링 프레임워크의 어노테이션 - @Valid
객체의 유효성을 검증하고, 검증 실패 시 예외를 발생시킵니다. - @RequestBody
Spring MVC 컨트롤러의 메서드에서 HTTP 요청 바디를 자바 객체로 변환해주는 어노테이션
크게 설명할건 없습니다. 다음부터가 슬슬 어려워질것 같네요.
'Back-end > Spring 기초개념' 카테고리의 다른 글
Entity에 setter를 사용하지 않는 진짜 이유 (1) | 2024.03.07 |
---|---|
JPA와 hibernate / Spring data JPA (0) | 2023.05.05 |
Instagram-clone 분석 (3) DTO (0) | 2023.04.23 |
Instagram-clone 분석 (2) entity (3) | 2023.04.22 |
Instagram-clone 분석 (1) (2) | 2023.04.19 |