Hayden's Archive

[Spring] Spring Web Security 설정 본문

Study/Java & Kotlin

[Spring] Spring Web Security 설정

_hayden 2020. 11. 10. 10:55

참고 :

책 - 코드로 배우는 스프링 웹 프로젝트 ( book.naver.com/bookdb/book_detail.nhn?bid=13993776 )

카페 - 구멍가게코딩단( cafe.naver.com/gugucoding )

codevang.tistory.com/266

 

Spring Security 설명

  • 거의 대부분 웹 기반 프로젝트에서 사용자의 권한이나 등급에 기반을 두는 로그인 체크를 이용
  • 스프링 시큐리티를 이용하면 다음과 같은 작업들을 간편히 처리할 수 있음
    • 로그인 처리와  CSRF 토큰 처리
    • 암호화 처리
    • 자동 로그인
    • JSP에서의 로그인 처리
  • 스프링 시큐리티의 기본 동작 방식 : 서블릿의 여러 종류의 필터(Filter)와 인터셉터(Interceptor)를 이용해서 처리
    • 필터는 서블릿에서 말하는 단순한 필터를 의미
    • 인터셉터는 스프링에서 필터와 유사한 역할
    • 유사점 : 특정한 서블릿이나 컨트롤러의 접근에 관여한다
    • 차이점 
      • 필터는 스프링과 무관하게 서블릿 자원. 서블릿 컨텍스트에 속하긴 하지만 스프링과 무관.
      • 인터셉터는 스프링의 빈으로 관리되면서 스프링의 컨텍스트 내에 속함. 스프링의 내부에서 컨트롤러를 호출할 때 관여하므로 스프링의 컨텍스트 내에 있는 모든 자원을 활용할 수 있음.
  • 스프링 시큐리티 이용 -> 인터셉터와 필터를 이용하면서 별도의 컨텍스트를 생성하여 처리
  • 스프링 시큐리티는 현재 동작하는 스프링 컨텍스트 내에서 동작 -> 이미 컨텍스트에 포함된 여러 빈들을 같이 이용해서 다양한 방식의 인증 처리가 가능하도록 설계 가능

 

 

Spring Security 최소한의 설정

이제 본격적으로 실습을 해보자.

스프링 프로젝트를 생성하고 pom.xml에 다음과 같이 추가한다.

<!-- Spring Security -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-web</artifactId>
	<version>5.3.5.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-config</artifactId>
	<version>5.3.5.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-core</artifactId>
	<version>5.3.5.RELEASE</version>
</dependency>
<!-- JSP에서 스프링 시큐리티와 관련된 태그 라이브러리 활용 -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-taglibs</artifactId>
	<version>5.3.5.RELEASE</version>
</dependency>

 

spring 폴더 아래 Spring Bean Configuration File 메뉴를 통해 security-context.xml 을 생성한다.

그리고 security-context.xml 의 네임스페이스에서 security 항목을 체크하고 저장한다.

 

그리고 나서 소스로 와보면 다음과 같이 되어 있다.

<?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-5.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


</beans>

 

이제 스프링 시큐리티를 스프링 MVC에서 사용하기 위해 필터를 이용해서 스프링 동작에 관여하도록 설정한다.

web.xml에 다음 코드를 추가한다.

<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>

 

프로젝트를 실행하면 다음과 같은 에러가 뜬다.

org.springframework.beans.factory.NoSuchBeanDefinitionException:

 

springSecurityFilterChain이라는 빈이 제대로 설정되지 않았다. 

web.xml에 <context-param>을 다음 코드로 수정하여 위에서 작성한 security-context.xml을 로딩하도록 설정한다.

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/spring/root-context.xml
		/WEB-INF/spring/security-context.xml
	</param-value>
</context-param>

 

security-context.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-5.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<security:http>
		<security:form-login/>
	</security:http>
	<security:authentication-manager>
	</security:authentication-manager>
</beans>

 

프로젝트를 실행하여 오류가 나지 않는 것을 확인한다.

 

 

접근 제한 설정

security-context.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-5.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<security:http>
		<security:intercept-url pattern="/sample/all" access="permitAll"/>
		<security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')"/>
		<security:form-login/>
	</security:http>
	<security:authentication-manager>
	</security:authentication-manager>
</beans>

특정한 URI에 접근할 때 인터셉터를 이용해서 접근을 제한하는 설정은 <security:intercept-url>을 이용한다. 여기서 pattern 속성은 URI의 패턴을 의미하고, access는 권한을 의미힌다.

'/sample/member'라는 URI는 'ROLE_MEMBER'라는 권한이 있는 사용자만 접근 가능!

 

<security:intercept-url>의 access의 속성값으로 사용되는 문자열은 1) 표현식과 2) 권한명을 의미하는 문자열을 이용할 수 있음

hasRole("ROLE_MEMBER")

 

표현식 없이 단순한 문자열만을 이용하고 싶은 경우에는 use-expression="false"로 지정. (보통은 표현식을 사용한다)

<security:http auto-config="true" use-expressions="false">
	<security:intercept-url pattern="/sample/member" access="ROLE_MEMBER"/>
	<security:form-login/>
</security:http>

 

설정을 반영하고 프로젝트를 실행하여 '/simple/all'로 접근하면 접근이 되는 반면 '/simple/member'는 로그인 페이지로 강제 이동한다.

(/login 에 해당하는 컨트롤러나 웹페이지를 만들지 않아도 그럼. 스프링 시큐리티가 기본으로 제공하는 테스트용 페이지.)