最新の安定バージョンについては、Spring Security 6.4.2 を使用してください! |
Remember-Me 認証
概要
Remember-me 認証または永続ログイン認証とは、セッション間でプリンシパルの ID を記憶できる Web サイトを指します。これは通常、Cookie をブラウザーに送信することで実現されます。Cookie は今後のセッションで検出され、自動ログインが行われます。Spring Security は、これらの操作を実行するために必要なフックを提供し、具体的な remember-me 実装を 2 つ備えています。1 つはハッシュを使用して Cookie ベースのトークンのセキュリティを保持し、もう 1 つはデータベースまたはその他の永続的なストレージメカニズムを使用して、生成されたトークンを保存します。
両方の実装が UserDetailsService
を必要とすることに注意してください。UserDetailsService
を使用しない認証プロバイダー(LDAP プロバイダーなど)を使用している場合、アプリケーションコンテキストに UserDetailsService
Bean が含まれていない限り機能しません。
単純なハッシュベースのトークンアプローチ
このアプローチでは、ハッシュを使用して便利な remember-me 戦略を実現します。基本的に、インタラクティブ認証が成功すると、Cookie がブラウザーに送信されます。Cookie は次のように構成されます。
base64(username + ":" + expirationTime + ":" +
md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
username: As identifiable to the UserDetailsService
password: That matches the one in the retrieved UserDetails
expirationTime: The date and time when the remember-me token expires, expressed in milliseconds
key: A private key to prevent modification of the remember-me token
そのため、remember-me トークンは、指定された期間のみ有効であり、ユーザー名、パスワード、キーが変更されない場合に限ります。特に、これには潜在的なセキュリティの課題があり、キャプチャーされた remember-me トークンは、トークンの有効期限が切れるまで、任意のユーザーエージェントから使用できます。これは、ダイジェスト認証の場合と同じ課題です。プリンシパルがトークンがキャプチャーされたことを認識している場合、プリンシパルはパスワードを簡単に変更し、発行されているすべての remember-me トークンをすぐに無効にすることができます。より重要なセキュリティが必要な場合は、次のセクションで説明するアプローチを使用する必要があります。あるいは、remember-me サービスはまったく使用しないでください。
名前空間の構成に関する章で説明されているトピックに精通している場合は、<remember-me>
要素を追加するだけで remember-me 認証を有効にできます。
<http>
...
<remember-me key="myAppKey"/>
</http>
通常、UserDetailsService
は自動的に選択されます。アプリケーションコンテキストに複数ある場合は、user-service-ref
属性で使用する必要があるものを指定する必要があります。値は UserDetailsService
Bean の名前です。
永久トークンアプローチ
このアプローチはいくつかの小さな修正 [ 1 ] がある記事 http://jaspan.com/improved_persistent_login_cookie_best_practice (英語) に基づいています。名前空間の構成でこのアプローチを使用するには、データソース参照を提供します。
<http>
...
<remember-me data-source-ref="someDataSource"/>
</http>
データベースには、次の SQL(または同等のもの)を使用して作成された persistent_logins
テーブルが含まれている必要があります。
create table persistent_logins (username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null)
Remember-Me インターフェースと実装
Remember-me は UsernamePasswordAuthenticationFilter
とともに使用され、AbstractAuthenticationProcessingFilter
スーパークラスのフックを介して実装されます。BasicAuthenticationFilter
内でも使用されます。フックは、適切なタイミングで具体的な RememberMeServices
を呼び出します。インターフェースは次のようになります。
Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
void loginFail(HttpServletRequest request, HttpServletResponse response);
void loginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication);
メソッドの機能に関する詳細については、Javadoc を参照してください。ただし、この段階では、AbstractAuthenticationProcessingFilter
は loginFail()
および loginSuccess()
メソッドのみを呼び出すことに注意してください。autoLogin()
メソッドは、SecurityContextHolder
に Authentication
が含まれていない場合に、RememberMeAuthenticationFilter
によって呼び出されます。このインターフェースは、基礎となる remember-me 実装に認証関連イベントの十分な通知を提供し、候補 Web リクエストに Cookie が含まれていて記憶したい場合は常に実装に委譲します。この設計により、任意の数の remember-me 実装戦略を使用できます。上記で、Spring Security が 2 つの実装を提供することを確認しました。これらを順番に見ていきます。
TokenBasedRememberMeServices
この実装は、単純なハッシュベースのトークンアプローチで説明されているより単純なアプローチをサポートしています。TokenBasedRememberMeServices
は RememberMeAuthenticationProvider
によって処理される RememberMeAuthenticationToken
を生成します。key
は、この認証プロバイダーと TokenBasedRememberMeServices
の間で共有されます。さらに、TokenBasedRememberMeServices
には、署名の比較のためにユーザー名とパスワードを取得し、正しい GrantedAuthority
を含む RememberMeAuthenticationToken
を生成できる UserDetailsService が必要です。ユーザーがリクエストした場合に Cookie を無効にするアプリケーションによって、何らかのログアウトコマンドが提供される必要があります。TokenBasedRememberMeServices
は Spring Security の LogoutHandler
インターフェースも実装しているため、LogoutFilter
と併用して Cookie を自動的にクリアすることができます。
remember-me サービスを有効にするためにアプリケーションコンテキストで必要な Bean は次のとおりです。
<bean id="rememberMeFilter" class=
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="theAuthenticationManager" />
</bean>
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class=
"org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"/>
</bean>
RememberMeServices
実装を UsernamePasswordAuthenticationFilter.setRememberMeServices()
プロパティに追加し、RememberMeAuthenticationProvider
を AuthenticationManager.setProviders()
リストに追加し、RememberMeAuthenticationFilter
を FilterChainProxy
に追加することを忘れないでください(通常は UsernamePasswordAuthenticationFilter
の直後)。
PersistentTokenBasedRememberMeServices
このクラスは TokenBasedRememberMeServices
と同じ方法で使用できますが、トークンを保存するには PersistentTokenRepository
でさらに構成する必要があります。2 つの標準実装があります。
テストのみを目的とした
InMemoryTokenRepositoryImpl
。トークンをデータベースに保存する
JdbcTokenRepositoryImpl
。
データベーススキーマは、上記の永久トークンアプローチで説明されています。