카테고리 없음

[Spring Security] JWT Tutorial (4) - 회원가입 & 권한검증

2023. 6. 17. 18:55

이번 포스팅에서는 마지막으로 회원 가입을 통해 데이터베이스에 회원 정보를 저장하고, 로그인을 통해 JWT를 생성하여, 권한에 따른 리소스에 접근 시 발급받은 JWT를 통해 검증하고 접근하는 로직을 개발해보자.

 

먼저 회원가입 로직을 개발하기 위해서 MemberService를 구현하자.

MemberService

 

[ SecurityUtil ] 

먼저, MemberService를 구현하기 앞서, 현재 유저의 이름을 반환하는 메서드를 가지고 있는 클래스를 생성하자.

public class SecurityUtil {
    private static final Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
    private SecurityUtil(){
    }
    public static Optional<String> getCurrentUsername(){
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if(authentication == null){
            logger.info("Security Context에 인증 정보가 없습니다.");
            return Optional.empty();
        }

        String username = null;
        if(authentication.getPrincipal() instanceof UserDetails){
            UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
            username = springSecurityUser.getUsername();
        }else if(authentication.getPrincipal() instanceof String){
            username = (String) authentication.getPrincipal();
        }
        return Optional.ofNullable(username);
    }
}

 

[ MemberService ]

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService {
    private final MemberRepository memberRepository;
    private final PasswordEncoder passwordEncoder;;

    // 회원가입 로직으로, 일반 회원이므로 ROLE_USER 권한
    @Transactional
    public Member signup(MemberDto memberDto){
        if(memberRepository.findOneWithAuthoritiesByUsername(memberDto.getUsername()).orElse(null) != null){
            throw new RuntimeException("이미 가입되어 있는 회원입니다.");
        }
        Authority authority = Authority.builder()
                .authorityName("ROLE_USER")
                .build();

        Member member = Member.builder()
                .username(memberDto.getUsername())
                .password(passwordEncoder.encode(memberDto.getPassword()))
                .nickname(memberDto.getNickname())
                .authorities(Collections.singleton(authority))
                .activated(true)
                .build();

        return memberRepository.save(member);
    }

    // 유저이름으로 유저 객체와 권한정보 가져옴
    public Optional<Member> getUserWithAuthorities(String username){
        return memberRepository.findOneWithAuthoritiesByUsername(username);
    }

    // SecurityContext에 저장된 username의 정보만 가져옴
    public Optional<Member> getMyUserWithAuthorities(){
        return SecurityUtil.getCurrentUsername().flatMap(memberRepository::findOneWithAuthoritiesByUsername);
    }
}
  • signup() 메서드를 통해 회원가입을 진행 (일반 유저 이므로 ROLE_USER로 설정)
  • getUserWithAuthorities()를 통해 유저 이름으로 유저 객체와 권한정보를 가져옴
  • getMyUserWithAuthorities() 를 통해  SecurityContext에 저장된 username의 정보만 가져옴

 

마지막으로 회원가입을 요청할 컨트롤러 계층을 개발해보자.


MemberController

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

    private final MemberService memberService;

    @PostMapping("/signup")
    public ResponseEntity<Member> signup(@Valid @RequestBody MemberDto memberDto){
        return ResponseEntity.ok(memberService.signup(memberDto));
    }

    @GetMapping("/user")
    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")
    public ResponseEntity<Member> getMyMemberInfo(){
        return ResponseEntity.ok(memberService.getMyUserWithAuthorities().get());
    }

    @GetMapping("/user/{username}")
    @PreAuthorize("hasAnyRole('ADMIN')")
    public ResponseEntity<Member> getMemberInfo(@PathVariable String username){
        return ResponseEntity.ok(memberService.getUserWithAuthorities(username).get());
    }
}
  • "/api/signup" 
    • memberService를 통해 RequestBody를 통해 MemberDto 정보로 회원가입을 진행
    • 성공하면 ResponseEntity에 담아 리턴
  • "/api/user" 
    • @PreAuthorize : USER, ADMIN으로 두 개의 권한 중 하나라도 가지면 접근이 가능
    • 현재 member의 정보를 조회하는 API
  • "/api/user/{username}"
    • @PathVariable : username
    • @PreAuthorize : ADMIN
    • 회원 정보를 username을 통해 검색하는 API

< 참고 자료 >

 

[무료] Spring Boot JWT Tutorial - 인프런 | 강의

Spring Boot, Spring Security, JWT를 이용한 튜토리얼을 통해 인증과 인가에 대한 기초 지식을 쉽고 빠르게 학습할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

엥재
엥재
Development Blog
엥재
Zerozae
엥재
전체
오늘
어제
  • 분류 전체보기
    • ABAP
    • 데브코스
      • TIL
    • AWS
    • Error
    • 정보처리기사
    • SQLD
    • CS
      • HTTP
      • DataBase
      • OS
    • 기타
      • 가상 면접 사례로 배우는 대규모 시스템 설계 기초
    • Programming
      • 기타
      • Spring
      • Java

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 어댑터 패턴
  • HTTP 메서드
  • 스프링 컨테이너
  • http 상태코드
  • 데몬스레드
  • 디자인 패턴
  • 함수형 인터페이스
  • 의존관계
  • 퍼사드 패턴
  • 교착 상태
  • 프로그래머스
  • 의존관계 주입
  • 퍼사드
  • 스프링 빈
  • 백엔드 데브코스
  • 싱글톤 컨테이너
  • DI컨테이너
  • 스프링
  • 빈 생명주기
  • HTTP
  • 상태코드
  • 캐시가능
  • 자바 Thread
  • IoC컨테이너
  • di
  • 상태 제어
  • 빈 스코프
  • 데브코스
  • 요구사항 확인
  • 컴포넌트 스캔

최근 댓글

최근 글

hELLO · Designed By 정상우.
엥재
[Spring Security] JWT Tutorial (4) - 회원가입 & 권한검증
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.