Spring Security _basic. 스프링 시큐리티와 csrf token의 개념

dwanGim·2022년 7월 4일
0

spring_basic

목록 보기
25/41

Spring Security

스프링 시큐리티는 특정 사이트로 들어오는 접근을 가로채서

로그인이 되어있는지 등을 검증한 다음 로직을 실행시켜주는 구조입니다.

원래 JSP에서는 "필터"를 이용해서 구현 가능했지만

스프링에서는 빈 컨테이너에서 관련 자원들을 같이 관리하기 떄문에

이미 작성된 빈들을 연계한 여러가지 인증 방식을

쉽고 간편하지만 복잡한 구조로 관리할 수 있습니다.

스프링 시큐리티 적용해보기

실습용 security_prj 프로젝트를 생성했습니다.

이후 spring security web / spring security config

spring seccurity core / spring security taglibs를 스프링 버전에 맞게

다운받은 후 spring-context.xml을 spring파일에 생성했습니다.

이후 namespace에서 security를 체크해줍니다.

스프링 시큐리티 용으로 bean을 관리하는 컨테이너입니다.

이때 디폴트로 생성한 xml 파일 스키마는 에러가 나기 때문에

초기코드를 수정해야합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/security 
	http://www.springframework.org/schema/security/spring-security.xsd
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd">

다음으로 web.xml설정을 합니다.

필터가 스프링 동작에 관여하도록 수정해주어야 합니다.

중요한 필터 경로이기 떄문에 오타가 나지 않도록 주의해야 합니다.

그리고 마찬가지로 web.xml을 수정해주어야 합니다.

root-context를 인증하는 경로 아래에 security-context의 경로도 추가해주어야

빈컨테이너에 있는 시큐리티 관련 로직을 web.xml이 인식합니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://Java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<!-- root-context와 security-context.xml을 잡아주는 경로 -->
		<param-value>/WEB-INF/spring/root-context.xml
					/WEB-INF/spring/security-context.xml
		</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	
	
	<!-- 한글 인코딩 설정 -->		
	<filter>
		<filter-name>encoding</filter-name>
		<filter-class>
			org.springframework.web.filter.CharacterEncodingFilter
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encoding</filter-name>
		<servlet-name>appServlet</servlet-name>
	</filter-mapping>
	

	<!-- security 필터 -->
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

위는 web-xml의 전문입니다.

스프링 시큐리티 컨트롤러의 작동원리

security-context.xml의 경로가 잡혔으면

Authentication Manager(인증매니저)가 추가되어야 합니다.

스프링 시큐리티에서는 반드시 비밀번호를 암호화해서 처리하도록 강제됩니다.

아직 암호화 설정을 하지 않았기 때문에 암호화 이전에 로그인만 테스트하기 위해

비밀번호 앞에 "{noop}"를 추가해 암호화 기능을 꺼두었습니다.

인증매니저가 설정되었으면 이제 권한에 따라 접속할 수 있는 형태를

따로따로 지정해주어야합니다.

spring security는 비회원 회원 운영자 3단계를 기본적으로 지원해주기 때문에

각각의 접속 주소를 컨트롤러에 세팅해주어야 합니다.

각각에 맞는 .jsp파일을 3개 만들고 접속을 확인해봅시다.

security의 구성 개념

필터와 시큐리티의 역할은

기본적으로 접속 요청을 스프링 시큐리티가 가로채서 검문한 다음

진행시킬 지 말지를 결정한다는 것 입니다.

이를 위해 security-context 내부에 어떤 url 접속을 가로챌 지

어떤 접근에 따른 처리를 할지 세팅이 필요했던 것 입니다.

security:http 내부에 security:intercept-url로 접근 url을 먼저

지정합니다.

pattern에는 접근 패턴을

access에 권한을 부여하고 위와 같이 hasRole('ROLE_직접부여권한명')을 적습니다.

스프링 시큐리티에 내장 디폴트 요소들이 있지만

어떻게 인터셉트를 하고 비정상적인 접속을 검문하는지 확인해보기 위해

commonController를 생성하여 커스텀해보겠습니다.

accessError.jsp를 생성하고 스프링 프레임워크를 임폴트해서

보안기능을 사용해보았습니다.

그리고 제가 사용하고 싶은 로그인 폼을 만든 후에 security-context.xml

내부의 security:form 속성을 변경하여 해당 주소를 감지하도록 합니다.

해당 form 속성을 수정하면 login-page를 설정할 수 있습니다.

구성된 로그인 폼으로 이동이 되는 것으로 확인되고 있습니다.

잘못된 사용자 정보를 입력하면 인터셉트한 security의 csrf token form이 방어를 해줍니다.

csrf token 은 무엇인가?

쿠키가 삭제될 때마다 바뀌는 csrf는

cross-site request forgery 공격이라는 이름을 가지고 있습니다.

csrf 검증로직이 없는 사이트는 form이나 img태그 내부의 링크 설정을

곧이곧대로 받아 처리하기 때문에 악의적으로 공격할 수 있는

약점이 있습니다.

만약 위와 같이 value 값을 미리 발급해둔 공격 로직을 설정한다면

공격자는 쉽게 링크설정을 할 수 있고

방어자는 value 값이 일치하기 때문에 모든 정보를 노출할 수 밖에 없게 됩니다.

csrf 토큰은 매번 value 값이 바뀌고 hidden으로 포함되어 들어가기 때문에

공격자 입장에서 고정된 쿼리문만 전송했을 때 계속 변하는 csrf토큰에

대응할 수 없게 됩니다.

매번 csrf 토큰이 새로 발급되고 랜덤으로 구성되기 때문에

csrf 토큰에 맞는 값을 검증시켜주어야 하는데 token의 랜덤변수가 40글자의 32제곱 변수로 변하기 때문에

엄청나게 크고 복잡하기 token을 맞추기가 어려워 사실 상의 완전방어가 가능해집니다.

결론 : spring security를 사용하자

일단은 여기까지 입니다.

spring security가 어떻게 사용자의 요청을 인터셉트하는지

csrf를 통한 방어기제는 어떻게 작용하는 지를 조금 이해한 것 같습니다.

다음 시간에 해당 내용을 더 깊게 정리하고 적용해보도록 하겠습니다.

profile
배울 게 참 많네요.

0개의 댓글