2022.01.04 TIL

듀듀·2023년 1월 4일
0

[ @AuthenticationPrincipal ]

세션 정보 UserDetails에 접근할 수 있는 어노테이션

@AuthenticationPrincipalUserDetails 타입을 가지고 있어서 UserDetails 타입을 구현한 PrincipalDetails클래스를 받아 User Object를 얻는다.

UserAdapter

  • User 정보를 직접 받는 게 아니라 어댑터 패턴을 이용해 받는다.
    - 정보 객체로 사용되는 객체는 UserDetails을 상속받아야 한다.
    (loadUserByUsername 메서드의 반환 타입이 UserDetails이기 때문)
    - 도메인 객체는 특정 기술에 종속되지 않도록 개발해야 한다는 것이 Best Practice
@Getter
public class UserAdapter extends CustomUserDetails{

    private Member member;
    private Map<String, Object> attributes;

    public UserAdapter(Member member){
        super(member);
        this.member = member;
    }

    public UserAdapter(Member member, Map<String, Object> attributes){
        super(member, attributes);
        this.member = member;
        this.attributes = attributes;
    }
}

CustomUserDetailsService

@Service
@Slf4j
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {

    private final MemberRepository memberRepository;
    private final HttpSession session;

    /** username이 DB에 존재하는지 확인 **/
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Member member = memberRepository.findByUsername(username).orElseThrow(() ->
                new UsernameNotFoundException("사용자가 존재하지 않습니다."));

        /** 시큐리티 세션에 유저 정보 저장**/
        return new UserAdapter(member);
    }
}

UserDetails를 상속 받은 UserAdapter을 통해 커스텀한 Principal를 사용할 수 있다.

인증을 담당하는 loadUserByUsername에서 Principal(UserDetails) 대신 위에서 만든 UserAdapter을 반환한다.
loadUserByUsername메서드의 반환되는 타입을 변경하기 위해 Principal(UserDetails)을 커스텀한 것이다.
(스프링 세션을 사용하면 첫 로그인 시에만 loadUserByUsername메서드가 호출된다.
JWT로 구현하였다면 매 요청마다 loadUserByUsername메서드가 호출된다.)

profile
나는 내 의지대로 된다.

0개의 댓글