본문으로 바로가기


1. 라이브러리 추가

Spring Security는 Spring 버전에 의존도가 있기 때문에, 의존성(dependency) 관련 버전을 반드시 확인하고 사용해야 한다. 무조건 내가 쓴 버전을 사용해야 한다는 것이 아니다. 의존성에 맞는 버전을 사용하면 된다. 버전을 찾고 싶으면 여기를 참고하면 된다. 자신이 쓸 스프링 시큐리티의 버전에 들어간 후, Compile Dependencies 에서 스프링 버전을 확인하여 사용하면 된다.


스프링 4.3.2 버전에 스프링 시큐리티 4.1.3 버전을 사용한다.


pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    <properties>
        <java-version>1.8</java-version>
        <org.springframework-version>4.3.2.RELEASE</org.springframework-version>
        <org.aspectj-version>1.8.4</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
        <spring.security.version>4.1.3.RELEASE</spring.security.version>
    </properties>
 
    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>${spring.security.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>${spring.security.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${spring.security.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        <version>${spring.security.version}</version>
    </dependency>
    <!--  -->
cs



2. Spring Security Filter 추가

spring security를 적용하기 위한 필터를 추가한다. 웬만하면 그대로 붙여넣자. 오타가 나면 곤란하다. 필터 이름을 임의로 변경해서는 안되기 때문이다. 스프링 시큐리티 내에서 클래스를 찾기 위해 지정한 이름이여서 변경하거나 오타가 발생하면 안된다. 그리고 url 에서도 확장자가 붙는 스타일이 아니 때문에 마음대로 변경해서는 안된다.


web.xml

1
2
3
4
5
6
7
8
9
10
11
    <!-- Spring Security Filter -->
    <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>
    <!--  -->
cs

- 03행: 필터의 이름은 반드시 springSecurityFilterChain 이여야 한다.

- 09행: 해당 필터가 적용될 URL 패턴을 모든 패턴을 의미하는 /*를 반드시 써야한다. 주소 호출할때 쓰던 *.do 등으로 쓰면 안된다.



3. Spring Security 설정 파일

Spring security의 설정을 위한 파일을 생성하자. 기본적으로 namespace를 "beans"로 사용할 것이다. 하지만 나는 "security"를 기본 namespace로 사용할 것이다. 아무거나 사용해도 무방하다. security를 기본 namespace로 사용하는 이유는 security 요소를 사용할 때 접두사 security를 생략하여 읽기 쉽게 하기 위함이다.


context-security.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security.xsd">
        
        <http auto-config="true" use-expressions="false">
            <intercept-url pattern="/**" access="ROLE_USER" />
        </http>
        
        <authentication-manager>
            <authentication-provider>
                <user-service>
                    <user name="user" password="userPw" authorities="ROLE_USER"/>
                    <user name="guest" password="guest" authorities="ROLE_GUEST"/>
                </user-service>
            </authentication-provider>
        </authentication-manager>
    
</beans:beans>
cs

- 02행: 기본 namespace를 security로 설정했다.

- 10행: auto-config 속성은 자동 설정을 뜻하고 use-expressions 속성은 intercept-url에 SpEL문법의 사용유무를 선택한다.

- 11행: 모든 URL을 접속(/**)하기 위해선 ROLE_USER 권한이 필요하다는 뜻이다. index 페이지 및 모든 페이지에 들어갈 수 있는 사람은 로그인을 한, 즉 권한을 가진(ROLE_USER) 사람만 들어 올 수 있다는 뜻이다. 나중에 되면 이곳에서 페이지의 경로(/admin/**, /user/**, ...)에 원하는 대로 권한 설정을 할 수 있다. 이것과 관련된 내용은 커스텀을 하면서 더 자세히 알게 될 것이다.

- 14행: 인증과 관련된 정보를 설정하는 태그이다.

- 15행: 인증에 대한 정보를 제공하는 제공자를 지정하는 태그이다.

- 16~20행: 사용자 정보를 설정하는 태그이다. 사용자 이름(ID), 권한, 비밀번호를 지정할 수 있다.



4. 설정 파일 등록

context-security.xml을 만들었으니, web.xml에 경로를 등록하자.

두가지 경우가 있다. 나는 프로젝트를 만들기 전에 구조를 변경했었다. 각자 맞는 경로를 등록하면 된다.


예1) web.xml

1
2
3
4
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/context-*.xml</param-value>
    </context-param>
cs

2


예2) web.xml

1
2
3
4
5
6
7
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/context-root.xml
            /WEB-INF/spring/context-security.xml
        </param-value>
    </context-param>
cs



4. 서버실행

서버를 실행하자. 근데 여기서 로그인 페이지를 안만들고 그냥 실행하는지 의문이 생길 수 있다. spring security에서 기본으로 제공하는 로그인 페이지를 사용할 것이다. 그렇기에 따로 페이지를 만들 지 않았다. 여기는 기초중의 완전 기초 설정만 설명하기 위해서다. 나중에 되면 로그인 페이지를 예쁘게 꾸미고, 거기에 맞춰서 시큐리티 설정을 다 만들어야 한다.


서버를 실행하면 만든 적도 없는 로그인 페이지가 뜰 것이다. 심지어 경로까지 정해져 있다(/login). 이게 바로 spring security에서 제공하는 기본 로그인 페이지이다. 그리고 index 페이지가 뜨지 않고 바로 로그인 페이지가 뜨는 이유는, context-security에서 모든 URL(/**)에 접속하기 위해선 권한이 ROLE_USER이여야 한다고 정했다. 그래서 권한을 알 수 없는(로그인하지 않은) 사용자에겐 로그인 하라는 로그인 페이지가 뜨는 것이다.


그럼 이제 로그인을 해보자. 사용자 등록 또한 context-security에서 했다. 먼저 접근 권한이 없는 ROLE_GUEST 부터 로그인 해보자.


403 에러 페이지가 떴다. 403 에러 페이지가 뜨는 게 정상이다. Access is denied. 접근이 불가하다. 접근 권한이 없다는 뜻이다. 우리는 ROLE_USER 권한을 가진 사용자만 접근할 수 있게 해놨기 때문이다. 그럼 이제 ROLE_USER 권한을 가진 user로 로그인 하자.



index 페이지가 나왔다. 로그인에 성공하였고, 해당 계정은 페이지에 접근할 권한이 있다는 뜻이다. 그럼 만약 비밀번호가 틀리거나, 없는 아이디를 사용하면 어떻게 될까? ROLE_GUEST 처럼 에러 페이지가 뜨는 걸까? 아니면 흔히 볼 수 있는 "비밀번호가 틀렸습니다."와 같은 메세지를 보여주는 걸까? 한번 해보자. 



다른 페이지로 넘어가지 않고 인증 실패를 확인할 수 있는 에러 메시지가 나왔다. 주소창에도 에러를 알려준다.


여기까지가 정말 기본 중의 기본, 완전 기초인 spring security 설정이다. 와, 쉽네! 이거 그대로 쓰면 되겠네! 라고 생각했다면 주먹을 쥐고 자신의 머리를 때려라. 당연히 커스텀해야 한다. 이렇게 볼품없는(?) 페이지와 울렁거리게 만드는 영어 에러 문구, 뭔가 잘 못 한 것만 같은 접근 불가 403 페이지까지... 전부 다 커스텀해야 한다. 이걸 그대로 프로젝트에 쓴다면 차라리 안쓰는 게 낫다. 쓸모없다. 복잡하고 어려워 보여도 스프링 시큐리티의 꽃은 커스텀이라고 생각한다. 


spring security를 차근 차근 잘 정리할 수 있기를 빌며!


GitHub