Home Spring Security, User Authentication
Post
Cancel

Spring Security, User Authentication

  • 사용자 인증 구현

ENTITY_설계

erd

CustomUserDetails

  • getAuthorities() : 접근한 사용자의 권한들을 가져오는 메소드.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Getter
@RequiredArgsConstructor
public class CustomUserDetails implements UserDetails {

  private final User user;

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return user.getRole().getRoleAuths().stream()
      .map(a -> new SimpleGrantedAuthority(
        a.getAuth().getName()
      )).collect(Collectors.toList());
  }

  @Override
  public String getUsername() {
    return user.getEmail();
  }

  @Override
  public String getPassword() {
    return user.getPassword();
  }

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

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

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

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

}


JpaUserDetailsService

  • SimpleGrantedAuthority : Spring security 가 기본 제공.
  • 애플리케이션 사용자의 이름에 해당하는 사용자를 찾으면 위에서 만들었던 CustomUserDetails에 user인스턴스를 래핑해서 반환
    • UsernameNotFoundException : 사용자를 못찾으면 반환하는 에러.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Slf4j
@Service
@RequiredArgsConstructor
public class JpaUserDetailsService implements UserDetailsService {

  private final UserRepository userRepository;

  @Override
  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
    Supplier<UsernameNotFoundException> usernameNotFoundExceptionSupplier = () -> new UsernameNotFoundException("problem during authentication!");
    User user = userRepository.findUserByEmail(email).orElseThrow(usernameNotFoundExceptionSupplier);
    log.info("JpaUserDetailsService user = {}", user);
    return new CustomUserDetails(user);
  }

}


AuthenticationProvider

  • authenticate() 실제 인증이 진행하고 유저 토큰을 리턴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthenticationProviderService implements AuthenticationProvider {

  private final JpaUserDetailsService jpaUserDetailsService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    String email = authentication.getName();
    UserDetails userDetails = jpaUserDetailsService.loadUserByUsername(email);

    log.info("authentication provider service userDetails = {}", userDetails.getUsername());
    log.info("authentication provider service userDetails = {}", userDetails.getPassword());
    log.info("authentication provider service userDetails = {}", userDetails.getAuthorities());

    return new UsernamePasswordAuthenticationToken(
      userDetails.getUsername(),
      userDetails.getPassword(),
      userDetails.getAuthorities()
    );

  }

  @Override
  public boolean supports(Class<?> authentication) {
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
  }

}
  • JpaUserDetailsService해당 서비스를 이미 @Bean으로 등록하고 있기 때문에
    SecurityConfiguration에 추가설정 불필요.


Exception

  • 이미 저장되어 있는 유저 정보로 로그인 시도 ⇒ 공포의 no_session 예외 발생

no_session

  • 영속성 유지를 위해 AuthenticationProviderService클래스의 authenticate 메소드에 @Transaction 설정

success

역할, 권한에 따른 접근 제한은 나중에….

This post is licensed under CC BY 4.0 by the author.