2.1. Introduction

- 스프링 네임스페이스
- 시큐리티 네임스페이스를 기본 네임스페이스로 사용하기

<beans:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:beans="http://www.springframework.org/schema/beans">
    ...
</beans:beans>

2.1.1 Design of the Namespace

- 가장 흔하게 사용되는 형태를 잡아서 네임스페이스를 설계했다. (네임스페이스 만드는 방법은 KSUG 1회 세미나에서 토비형님께서 발표해주셨었음. 다시 듣고 싶음..) 다음과 같이 나눠져 있다.

  • Web/Http Security - 가장 복잡한 부분이다. 필터들을 등록하고 그와 연관된 서비스 빈들을 등록한다. 인증, URL 보안, 로그인 페이지 보여주기, 에러 페이지 보여주기 등 많은 일을 한다.
  • Business Object (Method) Security - 서비스 계층을 보안(보완이 아니라 보안!!)하기 위한 옵션
  • AuthenticationManager - 프레임워크 내 다른 부분들에서 필요한 인증 요청을 다룬다. 간단하게 인증 담당자.
  • AccessDecisionManager - 해당 리소스에 접근 권한이 있는지 결정하는 곳. 간단하게 권한 담당자. 자동으로 기본값이 세팅 되는데 물론 커스터마이징 수도 있다.
  • AuthenticationProviders - 인증 담당자가 사용할 인증 방법들. 여러 가지 방법이 있겠지만, 기억하기, OpenID, 로그인 페이지가 가장 흔할듯.
  • UserDetailService - 인증 담당자가 사용자 정보를 가져올 때 사용하는 빈.

2.2. Getting Started with Security Namespace Cofiguration

여러분들이 Spring Security를 애플리케이션에 빨리 적용 인증, 권한 기능을 사용하길 원하다는 가정하게 설명한다.

2.2.1. web.xml 설정하기

가장 먼저 할 일은 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>

특정 URL을 후킹해서 스프링 ApplicationContext에 등록되어 있는 머시기 빈이 그 요청 처리 앞에 끼어들도록 하는 것임. 위 설정은 /* 이렇게 모든 요청을 가로채도록 해놨음.

2.2.2. 최소 <http> 설정

웹 보안을 위해 필요한 최소 설정은 아래와 같다.

  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
  </http>

모든 요청을 ROLE_USER 만 접근할 수 있다. 로그인 페이지에는 접근할 수가 있을까??? 없을 것 같은데.. 된다. 왜냐면 auto-config 때문에 설정된 <http-basic> 때문에.. 자세한건 아래에 있음.

<http> 엘리먼트 안에 <intercept-url> 엘리먼트 여러개를 설정할 수 있는데, 이 때 맨위에서 아래 순으로 가장 먼저 걸리는 녀석이 적용된다. 순서에 주의하자.

사용자 추가하기

  <authentication-provider>
    <user-service>
      <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
      <user name="bob" password="bobspassword" authorities="ROLE_USER" />
    </user-service>
  </authentication-provider>

아이디와 비번 권한 정보를 이렇게 직접 줄 수도 있다. 이 정보들을 프로퍼티 파일로 빼낼 수 도 있다. 자세한건 여기 참조. 그다지 안전해 보이지 않는 방법이다. 하지만 간단하게 적용할 수 있다는 것이 장점이다. 매우 작은 웹 애플리케이션에 적용하기엔 저 정도면 충분할 듯 하다. 여기에 정의한 사용자 정보들은 Authentication Manager가 인증 요청을 다룰 때 사용한다.

위에 설정을 10줄 밖에 안 했지만, 암묵적으로 몇개의 빈들이 설정된다. 로그인 처리라던지 "remember-me" 서비스 같은 것들이 자동으로 설정되었다. 이는 <http>에 auto-config 설정이 기본으로 되어있기 때문이다.

이전 버전에서 필터들의 순서가 이슈가 됐었는데 이제는 그런 걱정할 필요가 없다. 필터 등록하고 필터가 필요한 빈등록하는 일을 전부 <http> 엘리먼트가 책임진다. <http>는 옛날의 FilterChainProxy, <authentication-provider>는 옛날의 DaoAuthenticationProvider, <user-service>는 옛날의 InMemoryDaoImpl 라고 생각할 수 있다. 네임스페이스 처리 시스템이 ProviderManager는 자동으로 만들어주고 DaoAuthenticationProvider 얘를 거기에 자동으로 엮어서 등록한다.

이 내용은 Acegi를 아시는 분들만 이해하실 수 있습니다. 몰라도 별 지장은 없습니다.

2.2.2.1. What does auto-config Include?

auto-config 속성은 다음 코드를 압축시킨거다.

  <http>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login />
    <anonymous />
    <http-basic />
    <logout />
    <remember-me />
  </http>

2.2.2.2. Form and Basic Login Options

HTML 파일이나 JSP 파일을 만들지 않아도 Spring Security가 기본 로그인 화면을 만들어 준다. 물론 그걸 그냥 써도 되겠지만, 대부분 그러지는 않을 것이다. 다음과 같이 설정하여 별도의 로그인 폼을 지정할 수 있다.

  <http auto-config='true'>
    <intercept-url pattern="/login.jsp*" filters="none"/>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login login-page='/login.jsp'/>
  </http>

auto-config를 사용하는 상태에서 <form-login>도 설정하고 있는데, 이렇게 하면 기본 세팅값을 오버라이딩한다. /login.jsp 요청은 시큐리티 필터 처리를 하지 않도록 설정했다. 그래야 로그인 페이지에 접근할 수가 있다.

  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <http-basic />
  </http>

<http-basic /> 이라는 기본 인증은 설정 위치에 상관없이 가장 우선시 된다. 따라서, 제한된 영역에 접근하려고 할 때 로그인창을 띄운다.

2.2.3. Using other Authentication Providers

사용자 인증 방법을 여러가지 사용할 수 있는데, 사용자 정보를 보통은 DB나 LDAP 서버에 저장해 둔다. LDAP 네임스페이스는 LDAP 챕터에 나와있으니 여기서 다루진 않는다. UserDetailSerivce에 대한 구현체가 있다면 다음과 같이 등록할 수 있다.

 <authentication-provider user-service-ref='myUserDetailsService'/>

DB에서 직접 사용자 정보를 끌어올 거라면 다음과 같이 설정할 수 있다.

  <authentication-provider>
    <jdbc-user-service data-source-ref="securityDataSource"/>
  </authentication-provider>

위 설정에서 securityDataSource는 그냥 DataSource 타입의 빈 이름이다. 이 때 해당 데이터소스와 연관을 맺는 데이터베이스에는 Spring Secutiry 표준 사용자 테이블 스키마를 따르고 있어야 하는데, 스키마가 그와 다를 경우에는 JdbcDaoImpl 빈을 만들고 그 빈을 user-service-ref에 설정해줄 수있다.

user-service-ref에는 UserDeteailsService 타입의 빈을 등록할 수 있는데, JdbcDaoImpl은 UserDetailsService를 구현한 클래스이기 때문에 등록할 수 있는것이다.

2.2.3.1. Adding a Password Encoder

<authentication-provider>
  <password-encoder hash="sha"/>
  <user-service>
    <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER" />
  </user-service>
</authentication-provider>

위와 같이 <password-encoder has=sha"/>를 사용하여 해싱 알고리즘을 사용해서 암호화 할 수 있다. 사전어 공격을 막기 위해서 salt 값들을 사용할 수 있다.

<password-encoder hash="sha">
  <salt-source user-property="username"/>
</password-encoder>

너무 길어져서 Advanced와 Method Security는 Part 2에서 요약 하겠습니다.