Spring Security
"Spring Security" 프레임워크는 Spring 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 줌으로써 개발의 수고를 덜어 준다.
WebSecurityConfig
@Configuration
@EnableWebSecurity // Spring Security 지원을 가능하게 함
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf((csrf) -> csrf.disable());
http.authorizeHttpRequests((authorizeHttpRequests) ->
authorizeHttpRequests
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources 접근 허용 설정
.anyRequest().authenticated() // 그 외 모든 요청 인증처리
);
// 로그인 사용
http.formLogin(Customizer.withDefaults());
return http.build();
}
}
CSRF(사이트 간 요청 위조, Cross-site request forgery) : 공격자가 인증된 브라우저에 저장된 쿠키의 세션 정보를 활용하여 웹 서버에 사용자가 의도하지 않은 요청을 전달하는 것. CSRF 설정이 되어있는 경우 html에서 CSRF 토큰 값을 넘겨주어야 요청을 수신 할 수 있다. 쿠키 기반의 취약점을 이용한 공격이기 때문에 REST 방식의 API에서는 disable 가능. → http.csrf((csrf) -> csrf.disable());
Spring Security - Filter Chain
Spring에서 모든 호출은 DispatcherServlet을 통과하게 되고 이 후에 각 요청을 담당하는 Controller로 분배된다. 이 때, 각 요청에 대해서 공통적으로 처리해야할 필요가 있을 때 DispatcherServlet 이전에 단계가 필요하며 이것이 Filter 이다.
Spring Security도 인증 및 인가를 처리하기 위해 Filter를 사용하는데 이는 FilterChainProxy를 통해서 구현한다.
Form Login 기반 인증
Form Login 기반 인증은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인 페이지를 반환하는 형태
UsernamePasswordAuthenticationFilter
기본적으로 Form Login 기반을 사용할 때 username과 password 확인하여 인증하는 Filter
인증 과정
- 사용자가 username과 password를 제출하면 UsernamePasswordAuthenticationFilter는 인증된 사용자의 정보가 담기는 인증 객체인 Authentication의 종류 중 하나인 UsernamePasswordAuthenticationToken을 만들어 AuthenticationManager에게 넘겨 인증을 시도한다.
- 실패하면 SecurityContextHolder를 비움.
- 성공하면 SecurityContextHolder에 Authentication을 세팅 함.
SecurityContextHolder
SecurityContext는 인증이 완료된 사용자의 상세 정보(Authentication)를 저장한다.
SecurityContext는 SecurityContextHolder로 접근 할 수 있다.
// 예시코드
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
context.setAuthentication(authentication); // SecurityContext 에 인증 객체 Authentication 를 저장합니다.
SecurityContextHolder.setContext(context);
Authentication
현재 인증된 사용자를 나타내며 SecurityContext에서 가져올 수 있다.
- principal : 사용자를 식별함. Username/Password 방식으로 인증할 때 일반적으로 UserDetails 인스턴스이다.
- credentials : 주로 비밀번호, 대부분 사용자 인증에 사용한 후 비운다.
- authorities : 사용자에게 부여한 권한을 GrantAuthority로 추상화하여 사용한다.
<UserDetails>
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRoleEnum role = user.getRole();
String authority = role.getAuthority();
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(simpleGrantedAuthority);
return authorities;
}
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
UserDetails
UserDetailsService는 username/password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환 한다. Custome 하여 Bean으로 등록 후 사용 가능하다.
검증된 UserDetails는 UsernamePasswordAuthenticationToken 타입의 Authentication를 만들 때 사용되며 해당 인증객체는 SecurityContext에 세팅된다.
Spring Security : 로그인
스프링 시큐리티 사용 전 로그인 처리 과정
스프링 시큐리티 사용 후 로그인 처리 과정
Client의 요청은 모두 Spring Security를 거치게 된다.
상세 처리 과정
- Client - username 및 password 정보를 HTTP body로 전달(POST 요청)
- 인증 관리자(Authentication Manager) - UserDetailsService에게 username을 전달하고 회원상세 정보 요청
- UserDetailsService - 회원 DB에서 회원 조회. 조회된 회원 정보를 UserDetilas로 변환. 이를 인증 관리자에게 전달.
- 인증 관리자 - Client가 시도한 username/password와 UserDetailsService가 전달해준 UserDetails의 username/password 비교. 비교 시 Client가 보낸 Password는 평문이고, UserDetails의 Password는 암호문이기 때문에 Client의 password를 암호화해서 비교한다.
- 인증 성공 시 세션에 로그인 정보 저장 / 인증 실패 시 Error 발생
'Spring' 카테고리의 다른 글
Spring 데이터 검증 (Validation)하기 (0) | 2024.08.17 |
---|---|
Spring Security 접근 불가 페이지 만들기 (0) | 2024.08.17 |
Spring의 Filter 이해하기 및 구현하기 (0) | 2024.08.16 |
Spring에서 JWT 이해하기 + 쿠키와 세션 개념까지 (0) | 2024.08.16 |
Spring의 JPA와 Entity 이해하기 (0) | 2024.08.07 |