Spring Securiy -1-

mjdevv·2024년 2월 3일
0

Spring

목록 보기
4/4

스프링 시큐리티

스프링 진영에서 제공해주는 인증/인가 프레임워크


인증/인가(Auth)

1. 인증Authentication :
자원에 접근하는 사용자의 신원 확인. 즉, 거수자냐 아니면 가라치는지 확인하러 온 소대장이냐 암구어(호?) 등을 사용해서 신원을 확인.

2. 인가Authhorization :
자원에 접근하는 사용자의 권한이 있는지 여부. 즉, 내부인 인 건 확인 됐는데 이 탄약고(자원)에 출입 가능한 사람이냐 아니냐. 인증이 선결 돼야 하는 개념.

현실세계에서도 인증, 인가 개념은 존재한다. 같은 개념인데 그걸 디지털 리소스에 대해 적용한 것 뿐이다.


Spring security 아키텍처

아키텍처 구조는 위와 같다. 인증/인가를 구현한 프레임워크이기 때문에 스프링 진영에서 만들어 놓은 구조를 따라 비워 놓은 걸 쏙쏙 집어 넣어주면 인증/인가 기능을 구현을 할 수 있게 된다.

스프링 진영에서 어떤 식으로 인증/인가를 구현했는지 개념을 훑어보자. 들어가기에 앞서, 객체지향의 프리즘으로 위의 구조를 바라보자.

위의 화살표들은 각 과정마다 객체들이 주고 받는 메세지라고 이해하면 될 것 같다. 각 메세지들은 순서를 가지고, 해당 순서를 거쳐서 인증/인가가 이뤄지게 된다.

따라서 위의 아키텍쳐 구조를 이해하기 위해서는

  1. 구성요소(객체)
  2. 구성요소들이 주고 받는 메세지

크게 두개로 또개서 생각해볼 수 있다. 1번 2번 다 알아보긴 힘드니까, 1번 객체 단위로만 큰 덩어리로 쪼개서 해석해보자.


AuthenticationFilter

HttpRequest 객체를 인터셉트해서 auth 관련 필터링을 하는 객체. Delegation Pattern을 이용해서 톰캣 서블릿 컨테이너 안에 있는 필터 체인에서, 스프링 IoC 안에 있는 FilterChainProxy로 auth 관련 필터링을 위임한다. 어차피 스프링이나 톰캣이나 하나의 JVM 위에서 같이 굴러가고 있어서 위임이 가능하다.

위의 아키텍처 구성을 보자. 크게 아래 두 개의 대구조로 쪼개진다.

  1. Http 관련 요청을 처리하는 Web/Was 서버에 해당하는 Tomcat
  2. 자바 어플리케이션 프레임워크 Spring Container

서버 아키텍처 구조고, 밖에서 클라이언트의 Http(s) 요청이 날아왔다고 가정하자. 클라이언트에서 요청이 날아오면 해당 요청의 java object 표현인 HttpRequest 객체가 생성 되고, 그리고 해당 Http(s) 관련 요청을 처리하는 Tomcat의 Servlet Container에서 FilterChain을 타게 된다.

위 그림을 보자면 그 Tomcat 쪽 FitlerChain을 타는 와중에, Spring Security Framework에서 auth 관련 처리를 위해, Servlet Filter 안 DelegatingFilterProxy 인터페이스의 FilterChainProxy를 구현해서, HttpRequest 객체를 납치(?)한 뒤, 스프링 진영에서 구현한 기술로 Auth 관련 체크를 하게 된다.

public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
	
    ////.. some code //// 
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        String username = obtainUsername(request);
        String password = obtainPassword(request);

        if (username == null) {
            username = "";
        }
        if (password == null) {
            password = "";
        }

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

        // Authenticate the user
        return authenticationManager.authenticate(authRequest);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) throws IOException, ServletException {
        // If authentication is successful, proceed with the filter chain
        chain.doFilter(request, response);
    }
}

위 클래스는 스프링 시큐리티 프레임워크의 pre-built UsernamePasswordAuthenticationFilter 클래스를 extends 하고 있다.

inheritance heirchy 타고 올라가보면 Filter 인터페이스를 구현하고 있는데, 패키지 명을 보면 jakarta.servletFilter. 즉 서블릿 필터의 인터페이스다.

그런데 위와 같은 클래스들을 한 땀 한 땀 하나씩 설정해주는 건 귀찮기 때문에, 스프링 시큐리티에서는 config 설정 파일로 빼서 filter chain을 한꺼번에 설정해주는 방법을 제공해준다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //// some code... ////
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
	//// some code... ////
}

위와 같이 설정해주면 되고, HttpSecurity 클래스를 받아서 필터링 해주는데, 그럼 Servlet Container에서 Servlet Filter 타고 있는HttpRequest는 어디에 있는 거지 해서 찾아보니까, 파라메터로 받겠지 해서,

HttpSecurity를 열어 보니, RequestMatcher 클래스를 Has-a 관계로 가지고 있고, RequestMatcher를 열어 보면,

public interface RequestMatcher {
	//// some code... ////
	boolean matches(HttpServletRequest request);
	//// some code... ////
}

위와 같이 HttpServletRequest를 파라메터로 받는 걸 확인할 수 있다.


SecutriyContextHolder

  • SecurityContext : 현재 실행 스레드의 보안 관련 정보와 그 메타적 맥락에 대한 정보를 담고 있다.
    • Authentication : 인증 객체. 그냥 말 그대로 인증 관련 정보를 가진다.
      • Principal : Autheticated된 User 엔티티의 정보를 담고 있다. User Entity의 Identity를 표현하는 객체
        - Credentials : Principal 객체의 인증에 관련된 정보
      • Authorities : Principal 객체의 인가에 관련된 정보

그냥 스프링 시큐리티 프레임워크에서 인증 관련 정보를 관리하기 위해 자바 오브젝트로 auth 관련 정보들을 위와 같이 표현 했다고 이해하면 될 것 같다.


REFERENCE

[1] https://mangkyu.tistory.com/76
[2] https://docs.spring.io/spring-security/reference/index.html
[3] https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html

profile
방구석 언어기술자

0개의 댓글

관련 채용 정보