0. 시작하게 된 계기 및 다짐 😮

  • 이번 코드스테이츠의 백엔드 엔지니어링 개발자 부트캠프에 참여하게 되면서 현직개발자 분들의 빠른 성장을 위한 조언 중 자신만의 블로그를 이용하여 배운 것 들을 정리하는게 많은 도움이 된다 하여 시작하게 되었다.

    • 그 날 배웠던 것을 길지 않아도 좋으니 정리하며 복습하는 습관 기르기
    • 주말에 다음주에 배울 내용들을 예습
    • 코딩 문제와 java코드들은 꾸준히 학습
    • 자료구조를 이용한 알고리즘 문제 해결 학습

1. 학습 목표 😮

목표결과
Spring Security 환경 구성에 대해 배우고 구현O
Spring Security 인증(Authentication) 구성요소에 대해 이해O
Spring Security 인가(Authorization) 구성요소에 대해 이해O
Spring Rest Docs를 사용해서 API 문서를 생성 및 배포O

2. 정리 😮

Spring Security 개요

@어노테이션

  1. @Configuration

    • 개발자가 직접 제어가 불가능한 외부 라이브러리 or 설정을 위한 클래스를 bean으로 등록할 때
  2. @EnableWebSecurity

    • 스프링 시큐리티 필터가 스프링 필터체인에 등록되게 된다.
    • Spring FiterChain에 자동 등록 (SecurityFilterChain)이
  3. @Data

    • @ToString, @EqualsAndHashCode, @Getter : 모든 필드, @Setter : 정적 필드가 아닌 모든 필드, @RequiredArgsConstructor(DI의존성 주입중, '생성자 주입'을 코드없이 설정)를 모아놓은 어노테이션
  4. @EnableGlobalMethodSecurity(securedEnabled = true)

    • Secured 애너테이션이 활성화
    • SecurityConfig에서 접근 권한 설정이 아닌 Controller에서 애너테이션으로 관리
  5. @EnableGlobalMethodSecurity(prePostEnabled=true)

    • PreAuthorize, PostAuthorize 애너테이션이 활성화
  6. @Secured("ROLE_ADMIN")

    • @Secured는 1개의 권한을 주고 싶을 때 사용
  7. @PreAuthorize("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")

    • PreAuthorize는 1개 이상의 권한을 주고 싶을 때 사용
    • #을 사용하면 파라미터에 접근
  8. @PostAuthorize

    • 메서드가 실행되고 응답하기 직전에 권한을 검사하는데 사용



스프링 시큐리티(Spring Security)

  1. build.gradle

    • implementation 'org.springframework.boot:spring-boot-starter-mustache'
    • implementation 'org.springframework.boot:spring-boot-starter-security'
  2. 스프링 시큐리티

    • Spring Framework 기반의 application 인증(Authentication)과 인가(Authorization or 권한 부여) 기능을 가진 프레임워크
    • 스프링 기반의 애플리케이션에서 보안을 위한 표준
    • 스프링 인터셉터, 필터 기반의 보안 기능을 구현하는 것보다 스프링 시큐리티를 통해 구현하는 것을 권장
    • Java 8 이상의 환경이 필요하고 확장성을 고려한 프레임워크
  3. 필수 용어

    1). 주체(Principal)

    • 유저,기기,시스템등이 될 수 있지만, 보통 유저(사용자)를 의미

    2). 인증(Authentication)

    • 특정 리소스에 접근하는 사용자 확인
    • 주체의 신원을 증명( 주체는 자신 인증을 위한 신원 증명 정보(credential) 제시)
      • 유저일 경우, password

    3). 인가(Authorization = 권한부여)

    • 인증을 마친 유저에게 권한을 부여하여 특정 리소스에 접근할 수 있게 허해주는 과정
    • 인가는 반드시 인증 이후 수행되며, 권한은 롤 형태로 부여

    4). 접근통제(Access control)

    • 어떤 유저가 application resource에 접근 할지말지 통제하는 행위
    • 접근 통제 결정이 뒤따른다.
    • 리소스의 접근 속성과 유저에게 부여된 권한 또는 다른 속성들을 경정
  1. Spring Security 사용 이유

    • 이미 잘 구성된 체계적인 보안 흐름과 그에 포함이 되는 다양한 모듈을 제공

    1). 모든 요청에 대해 인증 요구

    2). 사용자 이름 및 암호를 가진 사용자가 양식 기반으로 인증을 허용

    3). 사용자의 로그아웃을 허용

    4). CSRF 공격을 방지

    5). Session Fixsation(세선 고정 공격)을 보호
    [공격자가 자신의 세션 id를 다른 사용자에게 줌으로써 공격하는 방법]
    - https://exhibitlove.tistory.com/318

    6). 보안 헤더 통합
    - HSTS 강화
    : 강제적으로 HTTPS Protocol로만 접속하게 하는 기능
    : https://m.blog.naver.com/PostView.nhn?blogId=aepkoreanet&logNo=221575708943&proxyReferer=https:%2F%2Fwww.google.com%2F
    - X-Content-TypeOptions
    - 캐시 컨트롤(정적 리소스 캐싱)
    - X-XSS-Protection XSS 보안
    [스크립트 공격 보안]
    - 클릭재킹을 방지하는 X-Frame 옵션 통합
    [웹 사용자가 자신이 클릭하고 있다고 인지하는것과 다른 어떤 클릭하게 속이는 악의적인 기법][잠재적으로 공격자는 비밀정보를 유출하거나 그들의 컴퓨터에 대한 제어를 획득]
    : 검색을 클릭하였는데 '구매'버튼을 누르게 하는것
    : https://ko.wikipedia.org/wiki/%ED%81%B4%EB%A6%AD%EC%9E%AC%ED%82%B9

    7). Servlet API 제공




Spring Security 코드 분석

[FilterChain @Bean등록 예제Code]

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable();
				http.headers().frameOptions().disable();

        http.addFilterBefore(new FirstFilter(), LogoutFilter.class);       //(0)
        http.authorizeRequests()                     //(1)
                .antMatchers("/user/**").authenticated() 
                .antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')")
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .anyRequest().permitAll();
                 //나머지 요청들은 권한 없이 접속 허가
                .and()
	   .formLogin()
                .loginPage("/login")
                 //권한이 없는 페이지들에 접속하였을시, login페이지로 이동;
                 //http 객체의 설정을 이어서 할 수 있게 하는 메서드

        return http.build();
    }

(0) 사용자가 정의한 Filter등을 SecurityFilterChain 내 원하는 필터 전에 적용시킬 수 있음
    - http.addFilterAfter(new FirstFilter(), LogoutFilter.class) : 해당 필터 이후에 적용
(1) authorizeRequests()는 시큐리티 처리에 HttpServletRequest를 이용한다는것을 의미
 
}


1) http.csrf().disable()
   - form태그로만 요청이 가능해지고 postman등의 요청이 불가능해진다.
   - Get요청을 제외한 상태를 변화시킬 수 있는 POST, PUT, DELETE 요청으로 부터 보호된다.
   - disable() 사용이 가능하게 만듬 현재
2). http.headers().frameOptions().disable()
   - X-Frame-Opions공격을 방지하기 위해 사용하지만, 여기서는 disable()로 사용가능하게 만듬
   - h2 연결할 때 필요한 옵션
   - 해당 페이지를 <frame>, <iframe>에서 렌더링할 수 있는지 여부를 나타내는데 사용
   - 즉, 해당 사이트내 컨텐츠들이 다른 사이트에 포함되지 않도록 하는것.
   - 여기서는 , h2를 사용하기 위해 disable사용

3). .antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')")
   - 해당 url의 경우 권한이 있을 경우에만 접속이 가능하게 만들어준다.
   - /, /login, /join 3개의 url은 로그인 없이, 권한 없이 접속이 가능하게 된다.



[WebMvcConfig.java] : mustache -> html 사용 설정

import org.springframework.boot.web.servlet.view.MustacheViewResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        MustacheViewResolver resolver = new MustacheViewResolver();
        resolver.setCharset("UTF-8");
        resolver.setContentType("text/html; charset=UTF-8");
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");

        registry.viewResolver(resolver);
    }
}

(1) Controller 반환값이 기본적으로 String 이나 @ResponseEntity와 같은 객체를 반환하는데, 
(2) String으로 반환할 시 해당 String에 맞는 View로 변환하여 보여주기 위함



[UserDetails 오버라이드 클래스 예제코드] : 현재 유저의 권한등의 정보를 세부적으로 가져오는 클래스

import com.codestates.section4week1.model.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

public class PrincipalDetails implements UserDetails {

    private Member member;

    public PrincipalDetails(Member member) {
        this.member = member;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collection = new ArrayList<>();
        collection.add(new GrantedAuthority() {
            @Override
            // User의 권한을 리턴
            public String getAuthority() {
                return member.getRole();
            }
        });
        return collection;
    }

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

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

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

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

    @Override
    // 암호 사용 기간이 지났는지에 관해 확인
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    //특정 사이트 규칙에 따라 return false로 설정
    public boolean isEnabled() {
        return true;
    }
}

- Authentication 타입 객체이며 안에 Member 정보가 있어야 합니다.
- 로그인 진행이 완료되면 security session을 만들어줍
- Security Session ⇒ Authentication ⇒ UserDetails



[UserDetailsService 오버라이딩 클래스 예제]

import com.codestates.section4week1.model.Member;
import com.codestates.section4week1.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class PrincipalDetailsService implements UserDetailsService {

    @Autowired
    private MemberRepository memberRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Member memberEntity = memberRepository.findByUsername(username);
        System.out.println("username : " + username);
        if(memberEntity != null) {
            return new PrincipalDetails(memberEntity);
        }
        return null;
    }
}
 - Security 설정에서 loginProcessingUrl(”/login”);으로 요청이 오면 자동으로 UserDetailsService 타입으로 IoC되어 있는 loadUserByUsername 함수가 실행
   [loginProcessingUrl("/login_proc")는,  로그인 Form Action Url, default: /login을 의미한다.]

 - 메서드 파라미터에 username이라고 되어있으면 form을 통해 username을 가져올 때 name이 반드시 매치되어야 합니다.
   1). 이름을 똑같이 변경해주거나
   2). SecurityConfig에 .loginPage() 아래에 .usernameParameter(”다른 이름")으로 추가해줘야 합니다.
 - loadUserByUsername 함수가 Authentication으로 값이 return 된다.



Filter와 FilterChain

  1. Overview
    1). 웹 컨테이너(서블릿 컨테이너)

    • CGI(Common Gateway Interface)로, 웹 서버 상에서 프로그램을 동작시키기 위한 방법을 정의한 프로그램
    • 웹 서버와 외부 프로그램에서 정보를 주고받는 규약
    • java에서는 CGI기능을 위해 웹 컨테이너를 사용(WAS)
    • 이 서블릿 컨테이너가 FilterConfig 객체와 함께 FilterChain인터페이스를 구현한 객체를 생성

    2). 필터 동작 흐름

    • Servlet Container가 FilterChain 구현한 객체를 생성
    • DelegatingFilterProxy 클래스는 Filter를 Spring Bean으로 사용할 수 있게 해주는 클래스로,
      서블릿 컨테이너 매커니즘으로 등록할 수 있음
    • 여러 서블릿 필터와 DelegatingFilterProxy를 통해서 applicationContext를 연결
    • DelegatingFilterProxy는 ApplicationContext에서 BeanFilter()를 찾아 실행
    • BeanFilter()는 FilterChainProxy가 되고 이는 스프링 시큐리티가 제공하는 특별한 Filter로 SecurityFilterChain이 됨
    • 이 FilterChainProxy를 통해 Security 관련 일들 실행




1. Filter [사진]

  • Servlet Filter를 기반으로 서블릿을 지원
  • HTTP요청과 응답을 변경할 수 있는 재사용 가능한 코드
  • Spring Security는 주여 보안에 대한 여러 처리를 Filter로 처리
  • 대표적으로, '인증'과 '인가'에 대한 처리
  • 자동 옵션을 사용하면 10개의 시큐리티 필터가 자동 설정

1). 클라 요청 -> Servlet Filter를 거침
2). DispatcherServlet과 같은 Serlvlet에서 요청이 처리됨




2. FilterChain

  • filter들이 사슬처럼 연결되어 각 처리되는 동작

  • 클라이언트가 앱에 요청을 보내고 컨테이너가 URI 경로를 기반으로 필터로 서블릿을 어떤걸 사용할 지 결정

  • 필터내의 체인에서 걸러질 수 있음

  • 다운스트림 필터와 서블릿을 사용해서 요청과 응답을 수정 가능

    • Filter 타입이 @Beans에 @Order를 붙이거나 Ordered를 구현한것
    • API의 일부로 순서를 가지는 FilterRegistationBean의 일부가 되는것
  • 컨테이너는 Servlet과 여러Filter로 구성된 필터 체인을 만들어 URI패스를 기반으로 HttpServletReqeust처리

  • DispatcherServlet에 의해 다뤄지기 전,후로 동작

  • 1개의 Servlet이 HttpServletRequest와 HttpServletResponse 처리를 담당

  • Filter는 FilterChain안에 있을 때 효력발휘




3. Filter 인터페이스

  • SecurityFilterChain 이후, Custom 필터들이 순차적으로 적용

1). public void init(FilterConfig filterConfig) throws ServletException

  • 필터를 웹 콘테이너 내에 생성한 후 초기화할 때 호출

2). public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException{ .... chain.doFilter(request, response)...}

  • 체인을 따라 다음에 존재하는 필터로 이동합니다. 체인의 가장 마지막에는 클라이언트가 요청한 최종 자원이 위치
  • 실제 필터의 역할을 하는 메소드
  • chain.doFilter(request,response) 를 통하여 응답의 필터링 작업 수행

3). public void destroy()

  • 필터가 웹 콘테이너에서 삭제될 때 호출




4. ★DelegatingFilterProxy★

  • ★ DelegatingFilterProxy 클래스는 Filter를 Spring Bean으로 사용할 수 있도록 합니다.

  • Spring Bean으로 등록되어있는 정보를 가져오기 위해서 이를 사용

  • 스프링 시큐리티가 모든 애플리케이션 요청을 감싸게하여 모든 요청에 보안이 적용되게 하는 서블릿필터

  • 서블릿 필터 라이프 사이클과 연계해 스프링 빈 의존성을 서블릿 필터에 바인딩

  • Spring IOC가 Filter bean을 가지고있고 이는 FilterChainProxy다.

  • 스프링 부트는 DelegatingFilterProxy라는 Filter 구현체로 서블릿 컨테이너의 생명주기와 스프링 ApplicationContext를 연결

  • 서블릿 컨테이너는 자체 표준을 사용해서 Filter를 등록할 수 있지만 스프링이 정의하는 Bean은 인식하지 못합

  • DelegatingFilterProxy는 표준 서블릿 컨테이너 메커니즘으로 등록할 수 있으면서도 모든 처리를 Filter를 구현한 스프링 빈으로 위임

  • DelegatingFilterProxy는 ApplicationContext에서 Bean Filter()을 찾아 실행합니다.

  • Bean Filter0는 FilterChainProxy가 됩니다.




5. FilterChainProxy

  • SecurityFilterChain은 FilterChainProxy로 등록된다
  • 스프링 시큐리티는 FilterChainProxy 로 서블릿을 지원합니다.
  • SecurityFilterChain을 통해 여러 Filter 인스턴스로 위임
  • FilterChainProxy는 빈이기 때문에 보통 DelegatingFilterProxy로 감싸져 있음
  • DelegatingFilterProxy는 서블릿 필터이며, Spring IOC 컨테이너가 관리하는 Filter Bean을 갖고 있음
  • Filter Bean은 FilterChainProxy이며 이 객체안에서 Security와 관련된 일들이 벌어진다고 생각할 수 있음




6. DelegatingPasswordEncoder

  • PasswordEncoder default : ElegatingPasswrodEncoder

    [Ex. PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder()]

1). 장점

  • 비밀번호를 현재 권장하는 저장 방식으로 인코딩을 보장
  • 비밀번호 검증은 최신 형식과 레거시 형식을 모두 지원
  • 나중에 인코딩을 변경할 수 있음

2). 커스텀 DelegatingPasswwordEncoder
[예제 Code]

String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());

PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders);

3). Password Storage Format

  • 비밀번호 포맷은 {id}encodePassword 형태
    [예제]
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG

 - PasswordEncoder id는 'bcrypt'
 - encodedPassword는 나머지 뒷부분
 - BcryptPasswordEncoder로 위임



Spring Security 인증 구성요소 이해


1. Spring Security 인증 처리 흐름 [사진]

1. Overview

  1. 사용자가 Username , password를 통해 인증요청

  2. AuthenticationFilter의 구현체인 UsernamePasswordAuthenticationFilter는 전달받은 Username과 Password를 가지고 UsernamePasswordAuthenticationToken을 생성

  3. 생성된 Authentication(Token)을 AuthenticationManager에 전달합니다.

  4. AuthenticationManager는 전달받은 Authentication을 다수의 AuthenticationProvider에 전달하여 유효성 검증 및 처리를 위임합니다.

  5. 입력받은 사용자의 인증 정보의 유효성 검증을 위해 UserDetailsService로 전달합니다.

  6. UserDetailsService는 loadUserByUsername() 메소드를 통해 사용자 정보를 조회하여 실제 존재하는 사용자인지, Username과 Password가 유효한지 검증합니다.

  7. 만약 6에서 사용자의 인증 정보 검증이 성공적으로 이루어졌다면 해당 사용자 정보를 활용해 UserDetails를 생성합니다.

  8. 생성된 UserDetails를 AuthenticationProvider에 전달합니다.

  9. authenticate() 메소드가 호출되며 UserDetails와 Authorities로 생성한 Authentication을 Manager에 전달합니다.

  10. 생성된 Authentication을 AuthenticationFilter에 전달합니다.

  11. AuthenticationFilter는 인증 처리가 모두 완료되어 해당 사용자의 인증 정보를 담고 있는 Authentication을 SecurityContext에 저장합니다.



Authentication

1. Overview

  1. Authentication(Token)은 인터페이스로 존재하며, 인증을 성공적 수행하면 사용자의 인증 관련 정보를 가지고있음

    • principal : 사용자 식별(식별자, 암호), UserDetails 인터페이스의 구현체( org.springframework.security.core.userdetails.User), 직접 Userdetails를 상속받아 구현할 수 있음
    • credentials : 암호, 사용자의 인증이 이루어진 후 지워짐
    • Authorities : AuthenticationManger에 의해 부여된 인가에 대한 정보, 권한 정보는 GrantedAuthority로 추상화한다.(구현체 : SimpleGrantedAuthority)
  2. 일반적으로 많이 사용되는 구현체는 UsernamePasswordAuthenticationToken

  3. UsernamePasswordAuthenticationToken은 고유 식별자와 암호로 간단하게 Authentication 생성가능



2. Authentication(인증)

  • 스프링 시큐리티는 종합적인 사용자 인증 처리를 기본 제공
  • 특정 리소스에 접근하는 사용자 확인시 사용
  • 일반적으로, 사용자 ID와 Password로 인증
  • 한번 인증 후, 사용자 식별 후 권한을 부여 가능(인가. authorization)



3. Password Storage

  • PasswordEncoder 인터페이스를 통해 단방향 변환수행
  • 인증에 사용할 credentials 정보를 저장
  • PasswordEncoder를 사용해서 저장하는 비밀번호는 인증 시점에 사용자가 입력하는 비밀번호와 비교용도
  • 발전방향 : SHA-256 -> 솔티드 패스워드 -> 단방향 함수(bcypt, PBKDF2, scrypt, argon2등)




Servlet Authentication Architecture

1. Architecture

  • 서블릿 인증에서 사용하는 스프링 시큐리티의 주요 아키텍처 컴포넌트 설명
  1. Overview

    • SecurityContextPersistenceFilter를 통해 SecurityContextRepository 라는 SecurityContext 저장소 객체에 해당 SecurityContext 영속화

    • 로그인 인증 요청시 새 Context객체를 생성하여 SecurityContextHolder에 등록후, 아래 과정들을 거쳐 인증에 성공하면

    • HttpSession에 해당 SecurityContext 저장 후(SecurityContextPerstenceFIlter), 요청이 끝나면 SecurityContextHolder를 비우고 SecurityContextRepository 에 해당 SecurityContext 를 다시 저장

    • 인증 후, 요청이 들어오면, 이 HttpSession에서 SecurityContext를 꺼내어 SecurityContextHolder에 저장

    • SecurityContext안에 Authentication 객체가 존재하면 계속 인증 유지

    • 추후, 요청시 등록이 되있냐 안되있냐에 따라 접근 허가 or 불가

    • 최종적으로 응답이 끝나면, 마찬가지로 SecurityContextHolder를 비움




1. SecurityContextHolder

  • 보안주체의 세부정보를 포함한 애플리케이션의 현재 보안컨텍스트에 대한 세부정보가 저장됨
  • SecurityContext를 관리한다.
  • SecurityContext 저장방식이 3가지 존재
  • 사용자 인증처리 방법

[Ex. Code]

SecurityContext context = SecurityContextHolder.createEmptyContext(); // (1)
Authentication authentication =
    new TestingAuthenticationToken("username", "password", "ROLE_USER"); // (2)
context.setAuthentication(authentication);

SecurityContextHolder.setContext(context); // (3)

(1). Holder를 이용해 빈 Context 생성
(2). Authentication(유저, 패스워드, 권한)을 생성
     [UsernamePasswordAuthenticationToken(userDetails, password, authorities)를 주로 사용]
(3) Holder에 이 Context를 저장
  1. SecurityContext

    • Authentication(권한)을 보관하는 역할, SecurityContext를 통해 Authentication 객체를 가져올 수 있음
    • SecurityContextHolder에 접근하는데 사용
  2. Authentication

    • principal(사용자 식별 정보), credential(비밀번호), authorities(사용자 권한들) 를 가지고 있음
    • 사용자가 인증을 위해 제공한 자격 증명(credential)이나 SecurityContext에 있는 현재 사용자의 자격 증명(credential)을 제공하며, AuthenticationManager의 입력으로 사용
  3. GrantedAuthority

    • Authentication에서 접근 주체(principal)에 부여한 권한
    • 현재 사용자가 가지고 있는 권한들을 추상화
    • Authentication.getAuthorities() 메서드로 접근, GrantedAuthority 객체의 Collection을 리턴
    • role(권한, 웹/메서드/도메인 인가)은 등에서 사용
  4. AuthenticationManager

    • 스프링 시큐리티의 필터가 인증을 어떻게 수행하는지에 대한 방법을 정의하는 API
    • 리턴한 Authentication을 SecurityContextHolder에 설정
    • 구현체로, ProviderManager를 사용
    • 적절한 Provider를 찾지못하면, 자신의 부모 객체에 저장된 ProviderManager도 검색하여 처리 가능하면 인증처리 위임
  5. ProviderManager

    • 가장 많이 사용하는 AuthenticationManager 구현체
    • AuthenticationProvider List에 위임
    • AuthenticationProvider를 통해서 인증 성공 or 실패 판단
    • 이(ProviderManager)를 사용하여 특정 인증 유형을 수행할 때 사용
  6. AuthenticationProvider

    • 각 구현체의 authenticate() 메서드에서 정의된 특정 유형에 따른 인증을 수행
    • ProviderManager에 AuthenticationProvider를 여러 개 주입할 수 있다.
    • AuthenticationProvider 마다 담당하는 인증 유형이 다르다.
    • DaoAuthenticationProvider는 이름/비밀번호 기반 인증 지원 (기본으로 적용되는 구현체)
    • JwtAuthenticationProvider는 JWT 토큰 인증 지원
  7. Request Credentials with AuthenticationEntryPoint

    • 클라이언트에 credential을 요청할 때 사용
  8. AbstractAuthenticationProcessingFilter

    • SecurityFilterChain의 로그인을 담당하는 필터
    • 인증에 사용할 Filter의 베이스
    • 여러 컴포넌트를 조합해서 심도 있는 인증 플로우를 구성



SecurityContextPersistenceFilter

1. SecurityContextPersistenceFilter

  • SecurityContext를 Persist하기 위한 구현체인 SecurityContextRepository를 가지고 있음
  • SecurityContextPersistenceFilter 클래스는 SecurityContext 객체를 영속화하는 역할을 수행하는 Filter
  • 인증 매커니즘 이전에 실행되어야 하여, 'Security Filter'들 중에서도2번째로 실행되는 Filter이다.
  • SecurityContextRepository 라는 SecurityContext 저장소 객체를 보유하고 있습니다.
    - 이를 통해 SecurityContext를 영속화하고 기존 저장된 SecurityContext객체를 꺼내어 SecurityContextHolder에 저장하는 등의 역할을 수행


2. 처리순서

  1. 클라이언트 요청 발생

  2. SecurityContextRepository 인터페이스의 loadContext() 메소드로 저장된 SecurityContext 객체를 가져옴

    • 기본으로 사용되는 저장소는 HttpSessionSecurityRepository 이며 HttpSession에 SecurityContext를 저장
  3. 해당 클라이언트의 요청이 모두 수행되고, 기존 SecurityContextHolder의 clearContext()로 비움

  4. SecurityContextRepository 에 해당 SecurityContext 를 다시 저장


3. SecurityContext 객체의 생성, 저장, 조회

1). 익명 사용자
- 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder에 저장한다.
- AnonymouseAuthenticationFilter에서 AnonymousAuthenticationToken 객체를 SecurityContext에 저장한다.

2). 인증 시
- 새로운 SecurityContext객체를 생성하여 SecurityContextHolder에 저장한다
- UsernamePasswordAuthenticationFilter에서 인증 성공 후 SecurityContext 에 UsernamePasswordAuthentication 객체를 SecurityContext에 저장한다.
- 인증이 최종 완료되면 Session 에 SecurityContext를 저장한다.

3). 인증 후
- Session에서 SecurityContext 꺼내어 SecurityContextHolder에서 저장한다.
- SecurityContext안에 Authentication 객체가 존재하면 계속 인증을 유지한다.

4). 최종 응답 시 공통
- SecurityContextHolder안의 SecurityContext객체에서 보관하던 인증정보를 반드시 초기화 해줘야 한다.
- SecurityContextHolder.clearContext() 메서드를 호출해 인증 정보를 초기화 한다.




2. SecurityContextRepository란?

  1. SecurityContextRepository
  • SecurityContext를 Persist하기 위한 구현체
  • 일반적으로 사용되는 구현체는 HttpSessionSecurityContextRepository



3. 피드백 😮

  • Spring Security란, Spring Framework 기반의 application의 인증 및 인가 기능을 가진 프레임워크를 뜻한다.


  • 인증 이란, 특정 리소스에 접근하는 사용자를 확인하는 행위이며 주체의 신원을 증명하는 행위이다.


  • 인가 란, 인증을 마친 유저에게 권한을 부여하여 특정 리소스에 접근할 수 있게 해주는 과정이다.


  • Spring Securiy는 서블릿 필터를 기반으로 서블릿(서버 쪽에서 실행되며 클라이언트의 요청을 동적으로 처리할 수 있게끔 도와주는 자바 클래스)을 지원하며 이 필터를 통하여 인증/인가에 대한 정보를 처리한다.


  • 서블릿 컨테이너에서 서블릿 필터들이 연결되어있는 FilterChain을 통해 Http요청을 받아 처리를 한 후, DispatcherServlet과 같은 곳에서 나머지를 처리하는데 이 FilterChain의 DelegatingFilterPorxy에서 FilterBean()을 통해 applcationContext를 연결해 SecurityFilterChain을 사용한다.


  • 인증 처리의 경우, 클라이언트로부터 username과 password를 받아 Authentication(Token)을 생성하고 AuthenticationManager에서 이를 받아 이후 처리를 한 후 해당 사용자의 정보를 SecurityContext(권한정보 등 저장)에 저장, 최종 응답 후 비우기


4. 앞으로 해야 될 것 😮

  • 매일 꾸준히 할 것
    • 꾸준히 velog 작성
    • Java 언어 및 Algorithm 공부(Coding-Test)
    • 틈틈히 운동 하기

  • 내일 해야 할 것
    • Spring Security 기본의 인가 처리 과정 학습
profile
Will be great Backend-developer

0개의 댓글