스프링 시큐리티에 대해 간단하게 개념 정리를 하고 단순 시큐리티를 적용해봅니다.

스프링 시큐리티 대략적인 기능

  • 사용자 권한에 따른 URI 접근 제어
  • DB와 연동 하는 Local strategy 로그인
  • 쿠키를 이용한 자동 로그인
  • 패스워드 암호화

이외에 여러 기능들이 존재합니다.

개념

시큐리티 사용을 앞서 인증(Authentication)인가(Authorization)이라는 개념을 알아야 합니다.

인증은 '증명하다'라는 의미로 예를 들어, 유저 아이디와 비밀번호를 이용하여 로그인 하는 과정 을 말합니다.

인가는 '권한부여'나 '허가'와 같은 의미로 사용됩니다. 즉, 어떤 대상이 특정 목적을 실현하도록 허용(Access) 하는 것을 의미합니다.

Web에서 인증은 해당 URL은 보안 절차를 거친 사용자들만 접근할 수 있다는 의미이고,
인가란 URL에 접근한 사용자가 특정한 자격이 있다는 것을 의미합니다.

스프링 시큐리티 적용

0. 선수조건

  • intellij의 springboot initializer를 통해 프로젝트를 생성합니다.
  • 메이븐을 사용합니다.
  • lombok을 사용합니다.

1. 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. Config 클래스 작성

import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.sql.DataSource;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/guest/**").permitAll()
                .antMatchers("/manager/**").hasRole("MANAGER")
                .antMatchers("/admin/**").hasRole("ADMIN");

        http.formLogin();
        http.exceptionHandling().accessDeniedPage("/accessDenied");
        http.logout().logoutUrl("/logout").invalidateHttpSession(true);

    }
  • @EnableWebSecurity 어노테이션을 추가합니다.
  • WebSecurityConfigurerAdapter 클래스를 상속 받습니다.
  • configure() 메소드를 오버라이드하여 작성합니다.
    • 파라미터는 HttpSecurity 객체를 받습니다.
  • 특정한 경로에 특정한 권한을 가진 사용자만 접근할 수 있도록 아래의 메소드를 이용합니다.
    • http.authorizeRequests()
    • http.authorizeRequests.antMatchers()
      • 빌더 패턴을 이용하고 있음
  • authorizeRequests()는 시큐리티 처리에 HttpServletRequest를 이용한다는 것을 의미합니다.
  • antMatchers()는 특정한 경로를 지정합니다.
  • permitAll()는 모든 사용자가 접근할 수 있다는 것을 의미합니다.
  • hasRole()은 시스템상에서 특정 권한을 가진 사람만이 접근할 수 있음
  • http.formLogin()은 form 태그 기반의 로그인을 지원하겠다는 설정입니다.
    • 이를 이용하면 별도의 로그인 페이지를 제작하지 않아도 됩니다.
    • '/login' 경로를 호출하면 스프링 시큐리티에서 제공하는 기본 로그인 화면을 볼 수 있게 됩니다.
  • 스프링 시큐리티가 웹을 처리하는 기본 방식은 HttpSession
    • 브라우저가 완전히 종료되면, 로그인한 정보를 잃게 됩니다.
    • 브라우저를 종료하지 않을 때, 로그아웃을 행해서 자신이 로그인 했던 모든 정보를 삭제해야 함
    • http.logout().invalidateHttpSession(true)

3. 로그인 입증

로그인을 위해서는 SecurityConfig 클래스에 AuthenticationManagerBuilder를 주입해서 인증에 대한 처리를 해야 합니다. AuthenticationManagerBuilder는 인증에 대한 다양한 설정을 생성할 수 있습니다. 예를 들어, 메모리상 정보를 이용하거나, JDBC, LDAP등의 정보를 이용해서 인증 처리가 가능합니다. 다음 예제는 메모리를 이용하는 예제입니다.

참고로 AuthenticationManagerBuilder는 인증 매니저를 생성하는 빌더입니다.

위의 SecurityConfig.java 클래스에 아래 메소드를 추가합니다.

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        log.info("build Auth global.......");

        auth.inMemoryAuthentication()
                .withUser("manager")
                .password("{noop}1111")
                .roles("MANAGER");
    }

그러면 아이디는 manager 패스워드는 1111로 로그인이 가능합니다.

4. 인증 방식

  • 인증 매니저(Authentication Manager)가 인증에 대한 실제적 처리를 담당합니다.
  • 인증 매니저는 인증과 관련된 모든 정보를 UserDetails 타입으로 반환합니다.
  • 이를 위해서는, 어떻게 관련 정보를 처리해야 하는지 판단할 UserDetailsService를 이용합니다.
  • 따라서, 개발자가 해야 하는 것은 UserDetailsService 인터페이스를 구현하고 인증 매니저에 연결시켜주면 됩니다.

5. 정리

  • 모든 인증은 인증 매니저를 통해 이루어 집니다.
  • 인증 매니저를 생성하기 위해서는 인증 매니저 빌드를 이용합니다.
  • 인증 매니저를 이용해 인증이라는 작업을 수행합니다.
  • 인증 매니저들은 인증/인가를 위한 UserDetailsService를 통해서 필요한 정보들을 가져옵니다.
  • UserDetails는 사용자의 정보 + 권한 정보들의 묶음입니다.

6. 같이 보면 좋은 것