1. 概要

この記事では、SpringSecurityRememberMe機能を設定する方法を示します。標準のCookieのみのアプローチではなく、永続性を使用したより安全なソリューションを使用します。

簡単な紹介として–ブラウザセッション間でログインの詳細を記憶するようにSpringを設定できます。 これにより、Webサイトにログインして、次にサイトにアクセスしたときに自動的にログに戻ることができます(その間にブラウザーを閉じた場合でも)。

2. 2つの「RememberMe」ソリューション

Springは、問題を解決するために2つのわずかに異なる実装を提供します。 どちらもUsernamePasswordAuthenticationFilterを使用し、フックを使用してRememberMeServices実装を呼び出します。

以前の記事で、Cookieのみを使用する標準のRememberMeソリューションについてはすでに説明しました。 このソリューションでは、 Remember-me というCookieを使用しました。これには、ユーザー名、有効期限、およびパスワードを含むMD5ハッシュが含まれています。 パスワードのハッシュが含まれているため、このソリューションはCookieがキャプチャされた場合に潜在的に脆弱です

そのことを念頭に置いて、2番目のアプローチを見てみましょう。 PersistentTokenBasedRememberMeServices を使用して、セッション間で永続化されたログイン情報をデータベーステーブルに格納します。

3. 前提条件–データベーステーブルを作成する

まず、データベースにログイン情報が必要です。データを保持するためにテーブルを作成する必要があります。

create table if not exists persistent_logins ( 
  username varchar_ignorecase(100) not null, 
  series varchar(64) primary key, 
  token varchar(64) not null, 
  last_used timestamp not null 
);

これは、起動時に自動的に作成されます次のXML構成を介して(メモリ内のH2データベースを使用):

<!-- create H2 embedded database table on startup -->
<jdbc:embedded-database id="dataSource" type="H2">
    <jdbc:script location="classpath:/persisted_logins_create_table.sql"/> 
</jdbc:embedded-database>

完全を期すために、永続性を設定する方法は次のとおりです。

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-h2.properties" })
public class DatabaseConfig {

    @Autowired private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.user"));
        dataSource.setPassword(env.getProperty("jdbc.pass"));
        return dataSource;
    }
}

4. Springセキュリティ構成

最初の重要な構成は、Remember-Me Http構成です( dataSource プロパティに注意してください)。

<http use-expressions="true">
    ...
    <remember-me data-source-ref="dataSource" token-validity-seconds="86400"/>
<http"> 

次に、実際のRememberMeServiceJdbcTokenRepository dataSourceも使用)を構成する必要があります。

<!-- Persistent Remember Me Service -->
<beans:bean id="rememberMeAuthenticationProvider" class=
  "org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
    <beans:constructor-arg value="myAppKey" />
    <beans:constructor-arg ref="jdbcTokenRepository" />
    <beans:constructor-arg ref="myUserDetailsService" />
</beans:bean>
 
<!-- Uses a database table to maintain a set of persistent login data -->
<beans:bean id="jdbcTokenRepository" 
  class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl"> 
    <beans:property name="createTableOnStartup" value="false" /> 
    <beans:property name="dataSource" ref="dataSource" /> 
</beans:bean>

<!-- Authentication Manager (uses same UserDetailsService as RememberMeService)--> 
<authentication-manager alias="authenticationManager"> 
    <authentication-provider user-service-ref="myUserDetailsService"/> 
    </authentication-provider> 
</authentication-manager> 

5. クッキー

前述したように、標準の TokenBasedRememberMeServices は、ハッシュされたユーザーパスワードをCookieに保存していました。

このソリューション– PersistentTokenBasedRememberMeServices は、ユーザー一意のシリーズ識別子を使用します。 これにより、ユーザーの初期ログインが識別され、その永続セッション中にユーザーが自動的にログインするたびに一定に保たれます。 また、ランダムトークンが含まれており、ユーザーが永続化されたremember-me関数を介してログインするたびに再生成されます。

ランダムに生成されたシリーズとトークンのこの組み合わせは永続化されるため、ブルートフォース攻撃はほとんど発生しません。

6. 実際には

ブラウザでremembermeメカニズムが機能していることを確認するには、次のことができます。

  1. RememberMeをアクティブにしてログインします
  2. ブラウザを閉じます
  3. ブラウザを再度開き、同じページに戻ります。 更新します。
  4. 引き続きログインします

Remember Meがアクティブでない場合、Cookieの有効期限が切れた後、ユーザーはログインページにリダイレクトされる必要があります。 Remember me を使用すると、ユーザーは新しいトークン/Cookieを使用してログインしたままになります。

ブラウザでCookieを表示したり、データベースで永続化されたデータを表示したりすることもできます(注–このために組み込みのH2実装から切り替えることをお勧めします)。

7. 結論

このチュートリアルでは、データベースの永続化されたRememberMeToken機能セットアップおよび構成する方法を説明しました。 これは、標準のCookieトークンベースの機能について説明した前回の記事のフォローアップでもあります。 パスワードの詳細がCookieに保持されないため、データベースアプローチの方が安全ですが、構成が少し多くなります。

このSpringSecurityRESTチュートリアルの実装は、 GitHubプロジェクトにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。