[Spring] 스프링 심화 - Spring Security 1

호호빵·2023년 1월 2일
0

Spring

목록 보기
19/24
  • [Spring] 스프링 심화 - Spring Security 1
    - 적용하기
    - Spring Security의 요소 확인

  • [Spring] 스프링 심화 - Spring Security 2
    - Default Form Login 방식 사용
    - UserDetails, UserDetailsService custom
    - 비밀번호 암호화 이해 및 적용

  • [Spring] 스프링 심화 - Spring Security 3
    - CustomSecurityFilter 적용
    - @AuthenticationPrincipal
    - @Secured
    - ExceptionHandling - 401, 403

Spring Security

  • Spring 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크
  • '인증'과 '권한'에 대한 부분을 Filter 흐름에 따라 처리
  • Filter는 Dispatcher Servlet으로 가기 전에 적용되므로 가장 먼저 URL 요청을 받지만, Interceptor는 Dispatcher와 Controller사이에 위치한다는 점에서 적용 시기의 차이가 있음
  • 보안과 관련해서 체계적으로 많은 옵션을 제공해주기 때문에 개발자 입장에서는 일일이 보안관련 로직을 작성하지 않아도 된다는 장점이 있다.
    -> 공식 문서

전체 처리 과정


0. 스프링 시큐리티 의존성 추가 시 일어나는 일

  • 서버가 기동되면 스프링 시큐리티의 초기화 작업 및 보안 설정이 이뤄짐
  • 별도의 설정이나 구현을 하지 않아도 기본적인 웹 보안 기능이 현재 시스템에 연동
    • 모든 요청은 인증이 되어야 자원에 접근이 가능
    • 인증 방식은 폼 로그인 방식과 HttpBasic 로그인 방식을 제공
    • 기본 로그인 페이지 제공
    • 기본 계정 한 개 제공 User, 랜덤문자열
# 미리 지정 가능

spring.security.user.name=user
spring.security.user.password=1234

1. 적용하기

@EnableWebSecurity

  • WebSeucurityConfiguration 등 웹 보안 활성화를 위한 여러 클래스들을 import
  • http라는 이름의 인자로 받아와서 제공되는 메서드들을 실행

WebSecurityConfigurerAdapter

  • 스프링 시큐리티에서 제공하는 웹 보안 기능의 초기화 및 설정이 가능하도록 해주는 클래스
  • getHttp()로 초기화, HttpSecurity 객체 생성
    • 아래 코드의 마지막에 this.configure를 호출함
    • 이를 통해 기본적인 보안 필터 호출 후, 추가적인 설정 및 기능들을 실행할 수 있도록 함
  • http.csrf()등의 메소드 호출, 각 메소드는 보안에 필요한 필터들을 호출하는 역할

configure()

  • @Override로 사용

  • HttpSecurity 클래스

    • 인증과 인가에 관련된 API들이 제공됨
    • http라는 인자로 받아와서 제공되는 메서드들 실행

1. build.gradle
2. WebSecurityConfig


# build.gradle
// 스프링 시큐리티
implementation 'org.springframework.boot:spring-boot-starter-security'

# WebSecurityConfig
@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable(); // CSRF 설정
        
        http.authorizeRequests().anyRequest().authenticated();

        http.formLogin();      // 로그인 사용
        
        return http.build();
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/images/**").permitAll()  // image 폴더를 login 없이 허용
                .antMatchers("/css/**").permitAll()
                .anyRequest().authenticated()      		// 어떤 요청이든 '인증'
                .and()
                    // 로그인 기능 허용
                    .formLogin()
                    .loginPage("/user/login")
                    .defaultSuccessUrl("/")
                    .failureUrl("/user/login?error")
                    .permitAll()
                .and()
                    // 로그아웃 기능 허용
                    .logout()
                    .permitAll();
    }
}

🔥 CSRF란?

  • CSRF(사이트 간 요청 위조, Cross-site request forgery)
    • 공격자가 인증된 브라우저에 저장된 쿠키의 세션 정보를 활용하여 웹 서버에 사용자가 의도하지 않은 요청을 전달하는 것
    • CSRF 설정이 되어있는 경우 html 에서 CSRF 토큰 값을 넘겨주어야 요청을 수신 가능
    • 쿠키 기반의 취약점을 이용한 공격 이기 때문에 REST 방식의 API에서는 disable 가능
    • POST 요청마다 처리해 주는 대신 CSRF protection 을 disable

2. Spring Security 요소 확인

- SecurityFilterChain

  • 스프링의 보안 필터를 결정하는데 사용되는 filter
  • session, jwt 등의 인증방식들을 사요하는데에 필요한 설정을 완전히 분리할 수 있는 환경 제공

- AbstractAuthenticationProcesssingFilter

  • 사용자의 credential을 인증하기 위한 베이스 필터

- UsernamePasswordAuthenticationFilter

  • AbstractAuthenticationProcessingFilter를 상속한 필터
  • 기본적으로 아래와 같은 Form Login 기반을 사용할 때 username, password를 확인하여 인증함.
    • form login 기반은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인 페이지를 반환하는 형태

- SecurityContextHolder

  • 스프링 시큐리티로 인증한 사용자의 상세정보를 저장
# 예시코드

SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication auth = new UsernamePasswordAuthenticationToken
					  (principal, credentials, authorities);
context.setAuthentication(auth);

SecurityContextHolder.setContext(context);
  • SecurityContext
    - SecurityContextHolder로 접근할 수 있으며 Authentication 객체를 가지고 있음.

- Authentication

  • 현재 인증된 사용자를 나타내며 SecurityContext에서 가져올 수 있음
  • principal : 사용자를 식별
    ㅤㅤㅤㅤㅤㅤ : username/password 방식으로 인증할 때 보통 UserDetails 인스턴스
  • credential : 주로 비밀번호, 대부분 사용자 인증에 사용하고 난 다음 비움
  • authorities : 사용자에게 부여한 권한을 GrantedAuthority로 추상화하여 사용
# UserDetails

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
	UserRoldEnum role = user.getRole();
    String authority = role.getAuthority();   // {"ROLE_USER"}
    
    SimpleGrantedAuthority sgAuth = new SimpleGrantedAuthority(authority);
    Collection<GrantedAuthority> authorities = new ArrayLsit<>();
    authorities.add(simpleGrantedAuthority);
    
    return authorities;
}

Authentication auth = new UsernamePasswordAuthenticationToken
					  (userDetails, null, userDetails.getAuthorities());


-> UsernamePasswordAuthenticaionTokenAuthenticationimplementsAbstractAuthenticationToken의 하위 클래스로, 인증객체를 만드는데 사용됨.

- UserDetailsService

  • username / password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환
  • custom하여 Bean으로 등록 후 사용 가능

- UserDetails

  • 검증된 UserDetails는 UsernamePasswordAuthenticationToken 타입의 Authentication을 만들 때 사용되며 해당 인증객체는 SecurityContextHolder에 세팅
  • custom하여 사용가능
    • UserDetailsService가 DB에 접근하여 user 객체를 가져와서 검증
    • UserDetails는 가져온 user의 정보를 활용해서 만든 객체
      -> 필터를 만들어서 위 두가지 활용하기





스프링 심화 자료- Spring Security
WebSecurityConfigurerAdapter 구조

profile
하루에 한 개념씩

0개의 댓글