Remember-me 인증은 BASIC 인증에는 사용되지 않는데, BASIC 인증은
종종 HttpSession을 이용하지 않기 때문이다.
Remember-me는 AuthenticationProcessingFilter와 함께
사용되며, 그리고 AbstractProcessingFilter 상위 클래스에
들어있는 훅을 통해 구현된다. 훅은 적절한 시기에 구상
RememberMeServices를 호출할 것이다.
인터페이스는 다음과 같다:
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response); public void loginFail(HttpServletRequest request, HttpServletResponse response); public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication);
위 메소드가 어떠한 동작을 하는지에 대한 자세한 사항은 JavaDoc을 참조하길 바라며,
이 단계에서는 AbstractProcessingFilter가 오직
loginFail()과 loginSuccess() 메소드만을
호출한다는 것만을 기억해 두기 바란다. autoLogin() 메소드는
SecurityContextHolder가 Authentication을
포함하고 있지 않을 때마다 RememberMeProcessingFilter에 의해 호출된다.
그러므로 이 인터페이스는 인증과 관련된 이벤트에 대해 충분히 통지를 하는,
기저의 remember-me 구현체를 제공하고 있으며, 후보(candidate) 웹 요청이
쿠키를 포함하고 있고 기억되기를 희망할 때마다 그 구현체에 위임한다.
이러한 설계 덕분에 다양한 remember-me 구현 전략을 구사할 수 있다.
단순함과 더불어 기록 및 생성 메소드를 지정하는 DAO 구현체가 필요 없도록 하기 위해
Acegi Security는 오직 구상 구현체인 TokenBasedRememberMeServices를 제공하며
이 구현체는 해싱을 이용하여 유용한 remember-me 전략을 완수한다. 본질적으로는
성공적으로 상호간의 인증을 이루기 위해 쿠키가 브라우저로 전달되며,
그 쿠키는 다음과 같이 구성되어 있다:
base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) username: TokenBasedRememberMeServices.getUserDetailsService()로 식별가능한 것 password: TokenBasedRememberMeServices.getUserDetailsService()로 전달받은 UserDetails에 대응되는 것과 일치하는 것 expirationTime: remember-me 토큰이 폐기될 때의 날짜 및 시간. 밀리세컨드 단위로 표현됨. key: remember-me 토큰의 변경을 방지하기 위한 비밀키
이러한 remember-me 토큰은 지정된 기간에 대해서만 유효하며, 사용자명과 비밀번호 및 키는 변경되지 않은 채로 제공된다. 특히 이는 가로채어진 remember-me 토큰이 특정 사용자 에이전트가 토큰이 폐기되는 시점까지 사용될 수 있다는 점에서 잠재적인 보안 문제를 내포하고 있다. 이것은 다이제스트 인증에 있는 것과 동일한 문제이다. 만약 인증 주체가 토큰이 가로채어졌다는 것을 인식할 경우, 인증 주체는 손쉽게 비밀번호를 변경하고 곧바로 발행된 모든 remember-me 토큰을 무효화(invalidate)할 수 있다. 하지만 좀더 중요한 보안이 필요할 경우 rolling token approach가 사용되어야 하거나(데이터베이스가 필요함) 아니면 단순히 remember-me 서비스를 사용하지 말아야 한다.
TokenBasedRememberMeServices는
RememberMeAuthenticationToken을 생성하며,
RememberMeAuthenticationToken은
RememberMeAuthenticationProvider에 의해 처리된다.
이러한 인증 제공자와 TokenBasedRememberMeServices간에는
key가 공유된다. 더불어
TokenBasedRememberMeServices는
UserDetailsService를 필요로 하는데,
이러한 UserDetailsService에서 서명을 비교할 목적으로
사용자명과 비밀번호를 검색할 수 있으며,
RememberMeAuthenticationToken을 생성하여 올바른
GrantedAuthority[]를 담는다. 사용자 요청에 의해
쿠키를 무효화하는 애플리케이션(일반적으로 JSP를 통해)에 의해 일종의
로그아웃 명령이 제공되어야 한다. 예제를 보려면 연락처(Contacts) 예제 애플리케이션의
logout.jsp을 참조하도록 한다.
remember-me 서비스를 활성화하기 위해 애플리케이션 컨텍스트에서 필요로 하는 빈은 다음과 같다:
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="rememberMeServices"><ref local="rememberMeServices"/></property>
</bean>
<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>
<property name="key"><value>springRocks</value></property>
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key"><value>springRocks</value></property>
</bean>
여러분의
AuthenticationProcessingFilter.setRememberMeServices()
프로퍼티에 RememberMeServices 구현체를 추가하는 것과
AuthenticationManager.setProviders() 목록에
RememberMeAuthenticationProvider를 포함하는 것, 그리고
FilterChainProxy(일반적으로 여러분의
AuthenticationProcessingFilter 바로 다음에)에
RememberMeProcessingFilter에 대한 요청을
추가하는 것을 잊지 않도록 한다.