본문 바로가기
프로그래밍

스프링 시큐리티 적용하기 (properties 인증 방법)

by 탁구치는 개발자 2013. 4. 20.

개인 프로젝트인 스프링 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>