728x90
반응형
SMALL

스프링 시큐리티란?

스프링 부트에서는 회원가입 및 로그인을 도오주는 스프링 시큐리티를 사용할 수 있다.
스프링 시큐리티는 스프링 기반 웹 애플리케이션의 인증과 권한을 담당하는 스프링의 하위 프레임워크이다. 
여기서 인증은 로그인 같은 사용자 신원을 확인하는 프로세스이고,
권한은 인증된 사용자가 어떤 일을 할 수 있는지 관리하는 것을 말한다.

 

스프링 시큐리티 설치하기

build.gradle

...
//Spring Security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
...

파일을 마우스 오른쪽 버튼을 눌러 [Gradle->Refresh Gradle Project]를 클릭하여 변경 사항 적용하면 설치가 완료된다.

이후 로컬 서버도 재시작하자

 

스프링 시큐리티 설정하기

서버 재시작 후 질문 목록 화면을 재접속 해보면 아래와 같은 화면이 나올 것이다.

스프링 시큐리티는 기본적으로 인증되지 않은 사용자가 웹서비스를 사용하지 못하도록 한다.

그래서 위와 같은 화면이 나온 것이다.

하지만 로그인 하지 않아도 조회할 수 있어야 하기 때문에 스프링 시큐리티를 설정해보자.

 

SecurityConfig.java

com.mysite.sbb 패키지에 작성한다.

package com.mysite.sbb;

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;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
	@Bean
	SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
		http
			.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
					.requestMatchers(new AntPathRequestMatcher("/**")).permitAll());
		return http.build();
	}
	
}
@Configuration 은 이 파일이 스프링의 환경 설정파일임을 의미한다.
@EnableWebSecurity는 모든 요청 URL이 스프링 시큐리티의 제어를 받도록 만드는 어노테이션이다.

내부적으로 SecurityFilterChain 클래스가 동작하여 모든 요청 URL에 이 클래스가 필터로 적용되어 URL별로 특별한 설정을 할 수 있게 된다.

 

다시 목록을 들어가면 이전처럼 인증 없이 들어갈 수 있다.

 

H2 콘솔 오류 수정하기

그런데 스프링 시큐리티를 적용했더니 H2 콘솔 로그인시 403에러가 뜬다.

이 오류는 서버가 클라이언트의 접근을 거부했을 대 반환하는 오류 코드이다.

 

잠시 질문 등록 페이지에서 개발자 모드로 소스코드를 보면

<input type="hidden" name="_csrf" value="0G04yuYo92U05ZJMCWioAvRd6dKEAINhDQr5AyxXzJNTN9xW4lterNUcx1EZhqp9OkWcOsE4xOq2YeJMPG_NZU81_KoyBu43"/>

이러한 input요소가 form태그 안에 자동생성되어 있다.

스프링 시큐리티 때문에 이와같은 CSRF 토큰이 자동으로 생성된 것이다.

 

따라서, H2 콘솔은 스프링 프레임워크가 아니므로 CSRF 토큰을 발행하는 기능이 없어 오류가 발생한다.

 

스프링 시큐리티가 CSRF 처리시 H2콘솔은 예외로 처리할 수 있도록 파일을 수정하자.

 

SecurityConfig.java

package com.mysite.sbb;

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;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
	@Bean
	SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
		http
			.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
					.requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
			.csrf((csrf) -> csrf
					.ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**")))
			;
		return http.build();
	}
	
}

재접속 해보면 로그인은 잘 수행됐지만 이렇게 화면이 깨진다.

H2 콘솔의 화면이 프레임 구조로 작성되었기 때문에 레이아웃이 이렇게 나뉘어져 있다.

스프링 시큐리티는 웹 사이트 콘텐츠가 다른 사이트에 포함되지 않도록 하기 위해 X-Frame-Options 헤더의 기본값을 DENY로 사용하는데, 프레임 구조의 웹 사이트는 이 헤더의 값이 DENY인 경우에 이같은 오류가 발생한다.

 

SecurityConfig.java

package com.mysite.sbb;

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;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
	@Bean
	SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
		http
			.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
					.requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
			.csrf((csrf) -> csrf
					.ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**")))
			.headers((headers)-> headers
					.addHeaderWriter(new XFrameOptionsHeaderWriter(
							XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN)))
			;
		return http.build();
	}
}

이제 로그인하면 정상적으로 동작하는 것을 확인할 수 있다.

728x90
반응형
LIST

+ Recent posts