본문 바로가기

IT

JWT와 Security를 활용한 인증, 인가 구현 3 ( REST API 구현)

728x90

https://sh970901.tistory.com/108 를 참고하여 REST API를 개발하기 위한 RsData를 생성하였다.

 

Member 컨트롤러를 생성하여 로그인 요청에 대한 처리를 작성해보자.

@PostMapping("/login")
public ResponseEntity<RsData> login(@Valid @RequestBody LoginDto loginDto) {
    Member member = memberService.findByUsername(loginDto.getUsername()).orElse(null);

    if (member == null) {
        return Util.spring.responseEntityOf(RsData.of("F-2", "일치하는 회원이 존재하지 않습니다."));
    }

    if (passwordEncoder.matches(loginDto.getPassword(), member.getPassword()) == false) {
        return Util.spring.responseEntityOf(RsData.of("F-3", "비밀번호가 일치하지 않습니다."));
    }
    log.debug("Util.json.toStr(member.getAccessTokenClaims()) : " + Util.json.toStr(member.getAccessTokenClaims()));

    String accessToken = memberService.genAccessToken(member);

    return Util.spring.responseEntityOf(
            RsData.of(
                    "S-1",
                    "로그인 성공, Access Token을 발급합니다.",
                    Util.mapOf(
                            "accessToken", accessToken
                    )
            ),
            Util.spring.httpHeadersOf("Authentication", accessToken)
    );
}

이전에 포스팅한 글을 참고하여 RsData에 대해 셋팅해두면 이렇게 간단히 API를 작성할 수 있다.

 

사용자에 대한 정보를 확인하기 위한 GetMapping을 추가해보자

@GetMapping("/me")
public ResponseEntity<RsData> me(@AuthenticationPrincipal MemberContext memberContext) {
    if (memberContext == null) { 
        return Util.spring.responseEntityOf(RsData.failOf(null));
    }

    return Util.spring.responseEntityOf(RsData.successOf(memberContext));
}

@AuthenticationPrincipal 는 어떤 과정으로 사용이 가능한 것일까? 

이전에 우리는 Security 관련 설정할 때 올바른 로그인 요청일 시 다음과 같은 함수를 추가했다.

그림 1

 

따라서 토큰을 통해 유효한 토큰인 경우 로그인 처리가 되어 @AuthenticationPrincipal를 사용할 수 있는 것이다.

memberContext == null 의 경우는 Security를 이용해서 로그인을 안했다면 아예 못들어오도록 설정도 가능하다. 

 

결과를 확인해보기위해 초기데이터 값을 생성했다.

@Bean
CommandLineRunner initData(MemberService memberService, MyBookService mybookService, PasswordEncoder passwordEncoder) {
    String password = passwordEncoder.encode("1234");
    return args -> {
        Member member1 = memberService.join("user1", password, "user1@test.com");
        Member member2 = memberService.join("user2", password, "user2@test.com");

        mybookService.write(member1, "제목 1", "내용 1");
        mybookService.write(member1, "제목 2", "내용 2");
        mybookService.write(member2, "제목 3", "내용 3");
        mybookService.write(member2, "제목 4", "내용 4");
    };
}

 

POSTMAN으로 실행 결과를 확인해보자.

정상 요청

올바른 요청의 경우 정상적으로 토큰을 발급하여 "S-1"이라는 메시지를 출력한다. 

 

잘못된 요청

user3이라는 존재하지 않는 계정으로 접속하니 예상한 결과를 확인할 수 있었다.

 

Auth - Bearer Token에 발급받은 토큰을 추가하여 사용자 정보를 조회해보자.

내 정보 요청

정상적으로 예상했던 사용자의 정보를 확인할 수 있다.