UserDetails UserDetailsSerive
시큐리티 세팅법을 간단하게 알아보자!
먼저 UserDetails와 UserDetailsSerive 인터페이스를 각각 구현해야한다.
@Getter
@RequiredArgsConstructor
public class LoginUser implements UserDetails {
private final User user;
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(() -> "ROLE_" + user.getRole());
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
}
@Service
@AllArgsConstructor
public class LoginService implements UserDetailsService {
private UserRepository userRepository;
// 시큐리티로 로그인이 될 때, 시큐리티가 loadUserByUsername() 실행해서 username 을 체크할 수 있음.
// 없으면 오류고
// 있으면 정상적으로 시큐리티 컨텍스트 내부 세션에 로그인된 세션이 만들어진다.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User userPS = userRepository.findByUsername(username).orElseThrow(
() -> new InternalAuthenticationServiceException("인증 실패")); // 나중에 테스트할 때 설명
return new LoginUser(userPS); // 찾았으면, 이 객체가 세션에 만들어짐.
}
}
SecurityConfig를 조작해보자
개발자가 원하는대로 SecurityConfig를 설정해줄 수 있다. 그 중 몇가지 설정을을 소개하겠다.
나중에 Jwt를 사용하기 위해 Jwt 필터도 등록해줬는데, 이건 다음 강의 정리때 Jwt개념과 함께 정리하겠다.
- BCryptPasswordEncoder
유저의 비밀번호를 암호화해 저장할 때 사용할 객체이다.
@Bean // IoC 컨테이너에 BCryptPasswordEncoder() 객체가 등록됨
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
- 기본 HTML로그인 페이지, 브라우저 팝업창 사용 안함
보통 프론트엔드와 함께 협업할 때 Security의 기본 로그인페이지는 사용하지 않는다. 마찬가지로 httpBasic도 사용하지 않으니 둘 다 비허용 처리를 해준다.
이때 SecurityFilterChain안에 넣어줘야한다.
http.formLogin(f->f.disable());
http.httpBasic(hb->hb.disable());
- 인증 실패, 인가 실패 Exception 가로채기
인증 또는 인가에 실패하면 예외가 터진다. 이 예외를 예쁘게 던지기 위해 미리 만들어준 커스텀 예외로 잡아준다. 바로 이전 글에 커스텀 예외에 대한 포스팅 글이 있다.
// Exception 가로채기
// 인증 실패
http.exceptionHandling(e -> e.authenticationEntryPoint((request, response, authException) -> {
CustomResponseUtil.fail(response, "로그인을 진행해 주세요.", HttpStatus.UNAUTHORIZED);
}));
// 권한 실패
http.exceptionHandling(e -> e.accessDeniedHandler((request, response, accessDeniedException) -> {
CustomResponseUtil.fail(response, "권한이 없습니다.", HttpStatus.FORBIDDEN);
}));
- 권한이 있어야 접근할 수 있는 페이지나 api 설정하기
특정 페이지나 api에 접근할 땐 인증이나 인가를 완료해야 접근할 수 있도록 만들고 싶을 수 있다.
이것도 SecurityConfig에서 설정해줄 수 있다.
http.authorizeHttpRequests(c ->
c.requestMatchers("/api/s/**").authenticated()
.requestMatchers("/api/admin/**").hasRole(""+ UserEnum.ADMIN)
.anyRequest().permitAll()
);
이렇게 설정해준 경우 /api/s/로 시작하는 곳에 접근하기 위해 인증, 즉 로그인을 한 상태여야하고, /api/admin/으로 시작하는 곳엔 ADMIN인가, 즉 특정 권한을 가진 ADMIN만 접근할 수 있다.
나머지엔 permitAll()로 모두가 접근할 수 있게 해준다.
'스터디 기록 > SpringBoot 심화 스터디' 카테고리의 다른 글
Long 타입 비교와 동적 쿼리 그리고 Join (0) | 2024.11.27 |
---|---|
서비스 테스트와 컨트롤러 테스트 (0) | 2024.11.19 |
Jwt 토큰 생성 세팅과 필터 등록하기 (1) | 2024.11.13 |
나만의 Exception 만들기 & 유효성검사와 AOP (0) | 2024.11.06 |