본문 바로가기
SpringBoot

[Spring Boot] 20. Spring Security (1) - Basic

by 청양호박이 2019. 12. 23.

이번에는 좀 복잡하다면 복잡한 Springpring에서 제공하는 보안에 대해서 알아보겠습니다. 이 보안을 제공하는 Spring Security에 대해서 알아보자면... 애플리케이션에 대한 Authentication 과 Authorization을 제공하는 Java 프레임워크입니다. 이 프레임워크는 Spring의 하위 프로젝트로 현재까지 지속적으로 버전이 업데이트 되고 있습니다.

 

보안에서 중요한 두가지 개념에 대해서 간단히 알아보자면... 

  • Authentication(인증) : 이 애플리케이션을 사용하기 위해 적합한 계정을 보유함을 확인하는 것
  • Authorization(권한) : 인증받은 사람이 해당 어플리케이션에서 어떤 수준으로 사용할지 부여하는 것

두가지 입니다. 딱 Spring Security가 제공하는 기능입니다. 과거에 복잡하게 구현한 로그인/로그아웃/권한체크 등을 Spring을 통해서 쉽게 구현이 가능해 집니다. 그럼 실질적인 개요와 코드로 확인해 보겠습니다. 이번 과정은 아래와 같이 나눠서 작성해보겠습니다.

 

  1. 개요 및 기본 로그인 + authentication 정보 확인
  2. Customize Form을 이용한 로그인 / 로그아웃
  3. 회원가입 및 password 암호화 / 권한체크
  4. 시간 여유가 되면 Non Form Rest 
  5. 역시나 시간 여유가 된다면 SPA 방식 적용 (아무래도 이건 View쪽 하나를 진행하고 적용해보는게...)

이번에는 첫번째로 개요 및 기본 로그인 / 로그아웃에 대해서 알아보겠습니다. Spring Boot에서 Spring Security의 구현로직은 아래와 같습니다.

 

사용자는 아무것도 모르고 그냥 원하는 페이지 혹은 로그인페이지에 접근합니다. 그럼 그 이후부터 동작로직은 Spring Boot 프로젝트 내에서 SecurityConfig에 설정한 내용으로 모두 관리가 됩니다. 그 뒷단에서 인증에 대한 부분을 책임지는 Authentication... 그리고 DB에서 사용자 정보를 가져오고 사용자가 입력한 정보를 비교하여 승인하는 등의 실질적인 로직이 들어가는 UserDetails... 부분이 작성됩니다.

 

그럼 이제 시작해 보겠습니다. 

 

 

1. 환경 구성


Spring Security를 사용하고, 간단한 화면을 구성하기 위해서 몇가지 Dependency를 추가해야 합니다. 총 2가지 입니다.

 

[pom.xml]

		<!-- Spring Security -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		
		<!-- Thymeleaf -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

dependency에 security를 추가한 이유는... SecurityConfiguration을 만들기 위함입니다. 그것을 위해서는 @EnableWebSecurity를 추가해야 하는데, 해당 dependency가 없다면 해당 어노테이션이 추가조차 되지 않습니다.

 

dependency에 thymeleaf를 추가한 이유는... Spring에 View를 구성하는 방법이 여러개 있겠지만 그중에 하나의 방법을 사용하기 위함입니다. 사용하는 방법은 뒤에 view page들을 만들면서 확인해 보겠습니다.

 

 

2. SecurityConfig


이름을 보고 눈치를 챌 수 있습니다. 해당 class는 config를 위한 class로 기존에 만들었던 다른 configuration class처럼 @Configuration 어노테이션을추가합니다. 또한 Spring Security를 명시하는 @EnableWebSecurity를추가합니다.

 

[SecurityConfiguration.java]

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
	
	@Autowired
	MyAuthenticationProvider myAuthenticationProvider;
	
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/static/css/**, /static/js/**, *.ico");
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/", "/home").permitAll()
			.anyRequest().authenticated();
		http.formLogin()
			.defaultSuccessUrl("/#/todo")
			.permitAll();
		http.logout()
			.logoutUrl("/logout")
			.logoutSuccessUrl("/home")
			.invalidateHttpSession(true)
			.permitAll();
		http.exceptionHandling().accessDeniedPage("/user/deny");
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(myAuthenticationProvider);
	}
	
}

해당 class는 WebSecurityConfigurerAdapter 클래스를 상속받아 해당 클래스에 정의된 메서드들을 @Override하여 사용합니다. 대상들은 아래와 같습니다. 

 

configure(HttpSecurity http) : 해당 메서드는 Spring Security를 통과할 대상을 설정합니다. 기준은 resources/static 디렉

                                      터리 입니다.

configure(HttpSecurity http) : http에 URL로 요청이 올때 이에 대한 보안을 구성하는 메서드 입니다. 보통 4가지 구성...

               1. authorizeRequests()는 httpServletRequest에 따라 접근을 제어합니다. antMatchers( )로 경로를 지정하고,

                  permitAll( ) / hasRole( )로 권한에 따른 접근 설정을 하게 됩니다.

               2. formlogin()는 form기반으로 인증을 수행하는 방법을 제공합니다. 로그인 정보는 http의 session정보를 

                  이용하고, 별도의 설정을 하지 않는다면 /login으로 접근하면 Spring에서 제공하는 기본 form을 사용!!!

               3. logout()은 로그아웃을 지원하는 메서드로 기본적으로 /logout으로 접근하면 http session을 제거합니다.

                  invalidateHttpSession(true)는 인증정보를 지우고 http session을 초기화 합니다.

               4. exceptionHandling()은 403에러가 발생하면 이동하도록 하는 메서드 입니다.

configure(AuthenticationManagerBuilder auth) : 

               모든 인증은 AuthenticationManager를 통해서 이루어 지는데 이를 생성하기 위해서는...Builder를 사용하고...

               AuthenticationProvider 인터페이스는 화면에서 입력한 로그인 정보와 DB의 정보를 비교해 주는 인터페이스

               입니다. 해당 인터페이스에 @Override되는 authenticate( )는 화면에서 사용자가 입력한 정보를 담고있는

               Authentication 객체를 가지고 있습니다.

 

 

3. AuthenticationProvider


우선 AuthenticationProvider 인터페이스에서 override되는 authenticate( )메서드가 어떻게 동작하는지만 우선 확인해 보겠습니다. 

 

[MyAuthenticationProvider.java]

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {

		String loginId = (String) authentication.getPrincipal();
		String loginPass = (String) authentication.getCredentials();
		
		System.out.println(authentication);
		
		//(principal, credentials, authorities)
		return new UsernamePasswordAuthenticationToken(loginId, loginPass, null);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return true;
	}
	
}

@Component 어노테이션을 추가하고... AuthenticationProvider 인터페이스를 추가합니다. 그렇게 되면 자동으로 대상 메서드를 @Override하게 되기 때문에, 위의 2개가 추가될 것입니다. 단지 출력용이기 때문에, authentication으로 넘어온 정보만 확인해 보도록 하겠습니다.

 

이렇게 딱 2가지의 class만 만들면... 자동으로 제공하는 login 페이지와 해당 페이지를 통해서 전송된 인증정보에 대한 확인까지 가능해집니다. 

 

Spring Boot의 서버를 실행시키고... /login을 입력하면 자동적으로이쁜 화면이 뜹니다!! 두둥

이 상태에서 ID와 Pass를 입력해 봅니다. 예상을 해본다면... .defaultSuccessUrl("/#/todo") 설정으로 해당 페이지로 이동하고, 서버에서보면 authentication정보가 출력 될 것입니다.

 

입력한 정보가 잘 넘어왔네요~ 이제 이것을 가지고 Service부분에서 DB의 정보와 일치하는지 확인하고... 권한 정보를 가져오는 등의 작업이 가능하겠습니다!!!

 

 

그럼 다음번에는 UserInfo에 대한 DB를 만들고 해당 DB에 생성한 계정에 대해서 인증정보를 확인하여 해당되는 페이지에 접속되는 것 까지 진행해 보겠습니다. 

 

-Ayotera Lab-

댓글