개인 프로젝트인 스프링 3.1 기반의 웹 애플리케이션에 시큐리티를 추가해 보기로 했다.
최종 구현 목표는 DB로 인증 및 URL 관리를 하는 것이며 일단 단계적으로 시큐리티가 어떤 기능을 지원하는지를 알아가기 위해서 오늘은 프로퍼티를 이용한 인증 및 권한 부여 방법에 대해서 설명하려고 한다.
먼저 스프링 시큐리티를 적용하기 위해서는 pom.xml에 라이브러리를 추가한다.
<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-config</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-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
그런 후 web.xml에 DelegatingFilterProxy 필터를 등록한다.
필터를 등록 한 후 url-pattern을 /* 로 설정하게 되면 모든 요청에 대한 처리를 시큐리티 필터가 받아 처리하겠다는 의미이다. 즉, 인증과 권한 부여를 통해 리소스 접근을 제어하겠다느 것이다.
그리고 한 가지 더 알아야 할 것은 스프링 시큐리티 필터를 등록하게 되면 DispatcherServlet보다 우선으로 적용되게 된다.
<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.xml에 아래 /WEB-INF/security-context.xml 설정 추가
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-context.xml
/WEB-INF/security-context.xml
</param-value>
</context-param>
시큐리티 메타 설정 파일
<?xml version=“1.0” encoding=“UTF-8”?>
<beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:security=“http://www.springframework.org/schema/security”
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-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd”>
<security:http pattern=“/common/css/**”
security=“none” />
<security:http pattern=“/common/img/**”
security=“none” />
<security:http pattern=“/common/js/**”
security=“none” />
<security:http auto-config=“true”>
<security:intercept-url pattern=“/**”
access=“IS_AUTHENTICATED_ANONYMOUSLY” />
<security:intercept-url pattern=“/admin/**” access=“ROLE_ADMIN”
/>
<security:form-login login-page=“/login.do”
login-processing-url=“/j_spring_security_check.do”
default-target-url=“/loginSuccess.do”
authentication-failure-url=“/loginFailed.do”
/>
<security:logout logout-url=“/j_spring_security_logout.do”
logout-success-url=“/logout.do”
invalidate-session=“true”
/>
</security:http>
<authentication-manager>
<authentication-provider>
<user-service properties=“classpath:conf/users-config.xml”
/>
</authentication-provider>
</authentication-manager>
</beans>
위의 설정 값 중 intercept-url 엘리먼트 정의를 보면 /admin/** 의 패턴이 access할 수 있는 권한은 ROLE_ADMIN으로 설정되어 있다.
/admin/** 패턴의 request URI로 들어오는 모든 요청에 대해서는 인증된 사용자가 ROLE_ADMIN 권한을 획득하고 있어야 리소스에 접근할 수 있다는 것이다.
users-config.xml
key에는 유저 아이디를 추가하고 엘리먼트 value 값에는 첫 번째 패스워드 그 이후로는 권한을 추가하면 된다. 권한은 여러개 추가 가능하며 콤마(,)로 구분하다.
<?xml version=“1.0” encoding=“UTF-8”
standalone=“no”?>
<!DOCTYPE properties SYSTEM
“http://java.sun.com/dtd/properties.dtd”>
<properties>
<comment>users</comment>
<entry key=“admin”>1111,ROLE_ADMIN,ROLE_USER</entry>
<entry key=“user”>2222,ROLE_USER</entry>
</properties>
마지막으로 로그인 페이지
j_spring_security_check.do URL로 로그인 요청을 보낼 때 j_username, j_password에 아이디 패스워드 값을 담은 채로 서버에 요청을 보내야 시큐리티 인증 및 권한 획득 작업을 진행한다.
<%@ page language=“java”
contentType=“text/html; charset=UTF-8” pageEncoding=“UTF-8”%>
<%@ taglib prefix=“c”
uri=“http://java.sun.com/jsp/jstl/core”%>
<%@ taglib prefix=“fn”
uri=“http://java.sun.com/jsp/jstl/functions”%>
<%@ taglib prefix=“fmt”
uri=“http://java.sun.com/jstl/fmt”%>
<html>
<head>
<title>Login
Page</title>
<style>
.errorblock {
color: #ff0000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body onload=“document.f.j_username.focus();”>
<h3>Login
with Username and Password (Custom Page)</h3>
<c:if test=“${not empty error}“>
<div class=“errorblock”>
Your login attempt was
not successful, try again.<br /> Caused : ${sessionScope[“SPRING_SECURITY_LAST_EXCEPTION”].message}
</div>
</c:if>
<form name=“f”
action=“<c:url value=“j_spring_security_check.do”
/>“
method=“POST”>
<table>
<tr>
<td>User:</td>
<td><input type=“text” name=“j_username”
value=“”></td>
</tr>
<tr>
<td>Password:</td>
<td><input type=“password” name=“j_password”
/></td>
</tr>
<tr>
<td colspan=“2”><input name=“submit” type=“submit”
value=“submit” /></td>
</tr>
<tr>
<td colspan=“2”><input name=“reset” type=“reset”
/></td>
</tr>
</table>
</form>
</body>
</html>