Technical Note/SPRING

Spring Framework를 통해서 인증(Authentication)과 허가(Authorization)에 관련된 작업을 한다면 여러 방법이 있을수있겠지만

일반적으로 Spring의 서브 프로젝트인 Spring security를 사용하게 된다.
Spring Security는 필터기반으로 동작하므로 Spring MVC 의 구현과 완전히 분리되고 
Spring과의 밀접한 연동으로 메서드 보안등의 여러가지 장점이 있다.
또한 Role기반의 허가를 지원하므로 경로별, 권한별 리소스 제한에 대해서도 많은 기능을 제공한다.
Spring Security를 사용할때 기본적인 Form인증을 사용하는 경우에 대해서 정리해 본다.

1. Spring Framework를 구성한다.

2. Spring security 사이트에서 배포본을 다운 받아 그 안의 jar파일을 라이브러리에 등록한다. (http://www.springsource.org/spring-security#download)

3. 다음의 필터 정의를 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>


이 필터 정의를 추가함으로서 해당 사이트의 모든 요청은 Spring Security를 통해서 처리된다. 

4. 다음의 설정파일을 추가한다. 관리 상 Spring Framework의설정 파일과 분리하는 편이 좋다

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security-3.1.xsd">



     <http pattern="/login" security="none"></http>   --> 위 코드는 login 요청에 대해서는 보안을 적용하지 않는다는 것을 의미한다. 
    
     <http auto-config="true" access-denied-page="/login?denied=true">
     <intercept-url pattern="/-*" access="ROLE_USER" />
       <form-login
        login-page="/login"
        authentication-success-handler-ref="loginSuccessHandler"
        authentication-failure-handler-ref="loginFailureHandler"
       />
     <logout logout-success-url="/login" />  

</http>

<beans:bean id="loginSuccessHandler" class="com.preludeb.auth.core.LoginSuccessHandler"></beans:bean>
<beans:bean id="loginFailureHandler" class="com.preludeb.auth.core.LoginFailureHandler"></beans:bean>

<beans:bean id="preludebUserService" class="com.preludeb.auth.core.PreludebUserService"></beans:bean>
<beans:bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder"/>

<authentication-manager> 
  <authentication-provider user-service-ref="preludebUserService">
   <password-encoder ref="encoder" />    
  </authentication-provider>
</authentication-manager>
</beans:beans>



좀더 자세히 설명

 <http pattern="/login" security="none"></http>  
 위 코드는 login 요청에 대해서는 보안을 적용하지 않는다는 것을 의미한다. Spring Security를 사용할 때 인증에 관련없이 보여주어야 할 부분(주로 로그인 페이지, 이미지 등의 정적인 리소스 등)은 
<http pattern="/s-ripts/-*" security="none"></http> 같은 형태로 패턴을 추가해 주면 된다. 이 패턴의 설정은 위부터 순서대로 적용되고 패턴매칭이 완료되면 아래의 피턴은 무시되므로 보안 설정을 무시하는 경로는 아래에 나오는 보안 설정 이전에 나와야 한다. 



     <http auto-config="true" access-denied-page="/login?denied=true">
     <intercept-url pattern="/-*" access="ROLE_USER" /> 
       <form-login 
        login-page="/login"
        authentication-success-handler-ref="loginSuccessHandler"
        authentication-failure-handler-ref="loginFailureHandler"
       />
     <logout logout-success-url="/login" />  


위 코드는 실절적으로 웹사이트 경로에 대한 권한 설정을 하는 부분이다.
auto-config = "true" 를 통해서 일반적으로 설정되는 많은 설정 부분이 자동으로 설정된다. 
access-denied-page="/login?denied=true"  부분은 인증을 통과 했지만 해당 요청에 맞는 권한이 없는 경우 보내지는 페이지 경로를 설정한다.  
<form-login 
        login-page="/login"
        authentication-success-handler-ref="loginSuccessHandler"
        authentication-failure-handler-ref="loginFailureHandler"
       /> 는 폼 인증을 사용하겠다는 정의이며, 로그인 페이지는 /login
       인증이 성공할때는 loginSuccessHandler 핸들러로 처리, 
       인증이 실패할때는 loginFailureHandler 핸들러로 처리하겠다는 것을 의미한다.

<logout logout-success-url="/login" /> 은 로그아웃시 리다이렉트 될 페이지를 정의한다.



<beans:bean id="loginSuccessHandler" class="com.preludeb.auth.core.LoginSuccessHandler"></beans:bean> 
는 로그인 성공시 처리할 핸들러 빈의 정의이다. 해당 구현은 잠시 후 살펴본다.


<beans:bean id="loginFailureHandler" class="com.preludeb.auth.core.LoginFailureHandler"></beans:bean>
는 로그인 실패시 처리할 핸들러 빈의 정의이다. 해당 구현은 잠시후 살펴본다.



<beans:bean id="preludebUserService" class="com.preludeb.auth.core.PreludebUserService"></beans:bean>
는 로그인 처리과정에서 UserDetails 객체를 생성하는 UserDetailsService의 빈의 정의이다. 해당 구현은 잠시 후 살펴본다.


<beans:bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder"/>
는 Spring Security에서 제공하는 패스워드 인코더의 빈 정의이다. 이 인코더는 random salt를 적용하는 단 방향 해시이며
일반적인 해시와 동일한 형태로 사용하면 된다.
구 버전 spring security 의 경우에는 이 인코더를 지원하지 않으므로 SHA나 MD5 해싱을 이용한다.