스프링 시큐리티 기본 설정(UserDetailsServiceImpl.class, UserDetailsImpl.class) - 시큐리티 5편

JaeYeop·2022년 2월 12일
2
post-custom-banner

전체적인 흐름도는 이전 글에서 꼭 확인

https://velog.io/@jjy5349/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EA%B8%B0%EB%B3%B8-%EC%84%A4%EC%A0%95SecurityConfig.class-JwtTokenProvider.class-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-3%ED%8E%B8

UserDetailsImpl

@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserDetailsImpl implements UserDetails {

    private String email;

    private String password;

    private UserRole role;

    private LoginProvider loginProvider;

    private String nickname;

    private ProfileImage profileImage;

    private String refreshToken;

    @Builder
    public UserDetailsImpl(String email, String password, UserRole role, LoginProvider loginProvider, String nickname, ProfileImage profileImage, String refreshToken) {
        this.email = email;
        this.password = password;
        this.role = role;
        this.loginProvider = loginProvider;
        this.nickname = nickname;
        this.profileImage = profileImage;
        this.refreshToken = refreshToken;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> grantedAuthority = new ArrayList<>();
        grantedAuthority.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return getRole().toString();
            }
        });

        return grantedAuthority;
    }

    @Override
    public String getUsername() {
        return email;
    }

    @Override
    public String getPassword(){ return password;}

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

UserDetailsImpl은 Authentication을 담고있는 UserDetails 인터페이스를 상속하는 클래스이다.

SecurityContextHolder에 담을 Authentication 객체를 만들 때 사용할 예정이고 나는 위와 같이 정의 해주었다.

UserDetailsServiceImpl

@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepository;

    /**
     * methodName : loadUserByUsername
     * author : Jaeyeop Jung
     * description : Context에 담기 위해 UserDetails를 implement한 UserDetailsImpl을 반환
     *
     * @param id
     * @return id를 통해 찾은 UserDetailsImpl 객체
     */
    @Override
    @Transactional
    public UserDetailsImpl loadUserByUsername(String id) { 

        User findUser = userRepository.findById(Long.parseLong(id))
                .orElseThrow(() -> new IncorrectDeleteUserRequestException(""));

        if(findUser != null){
            return UserDetailsImpl.builder()
                    .email(findUser.getEmail())
                    .password(findUser.getPassword())
                    .role(findUser.getRole())
                    .loginProvider(findUser.getLoginProvider())
                    .nickname(findUser.getNickname())
                    .profileImage(findUser.getProfileImage())
                    .refreshToken(findUser.getRefreshToken())
                    .build();
        }

        return null;
    }
}

자 그러면 UserDetailsServiceImpl을 보자.

우리는 토큰을 검증하고 정상적인 토큰이라면 SecurityContextHolder에 담을 Authentication 객체를 만들어야한다.

    public Authentication getAuthentication(String token){
        UserDetailsImpl userDetails = userDetailsService.loadUserByUsername(String.valueOf(this.findUserIdByJwt(token)));
        return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
    }

그러기 위해서 이전 글의 JwtTokenProvider.class에 정의했던 getAuthentication 메소드를 사용할 것이다.

이 메소드는 UserDetailsServiceImpl의 loadUserByUsername 메소드를 실행한다. 그러면 UserDetailsImpl을 만들어서 반환 해준다.

다시 getAuthentication 메소드에서는 UsernamePasswordAuthenticationToken라는 시큐리티에서 사용하는 AuthenticationToken을 만들어서 반환 해준다.

최종적으로 JwtAuthenticationFilter에서는 SecurityContextHolder에 해당 반환 값을 담음으로 권한처리를 할 수 있게 해준다.

다음 글에서

profile
이게 왜 틀리지... (나의 메모용 블로그)
post-custom-banner

0개의 댓글