15.3.5. Remember Me

Seam Security は多くの Web ベースアプリケーションに共通した Remember Me 機能の 2 種類のモードに対応しています。ユーザー名をユーザーのブラウザにクッキーとして保存しブラウザにパスワードを記憶させるモードと、固有のトークンをクッキーに保存してユーザーがそのサイトに戻ったときにパスワードを入力することなく自動的に認証できるモードです。

警告

これはユーザーにとっては便利ですが、 クライアントのマシンで永続クッキーを使った自動のクライアント認証はクロスサイトスクリプティング (XSS) のセキュリティホールによる影響が拡大されるため危険です。 認証クッキーがない場合、 攻撃側が XSS で盗むことができるクッキーはユーザーの 現在のセッションクッキー のみです。 このため、 攻撃はユーザーがセッションを開いている間しか発生しません。 永続の Remember Me クッキーが盗まれると攻撃側はいつでも認証なしでログインができます。 自動のクライアント認証を使用したい場合は XSS 攻撃に対して Web サイトを保護することが不可欠となります。
ブラウザのベンダーはこの問題に対抗する Remember Passwords 機能を導入しました。 ブラウザは特定の Web サイトやドメインへのログインに使用するユーザー名とパスワードを記憶して、 アクティブなセッションがない場合はそのログインフォームに自動入力を行います。 Web サイトでのログインのキーボードショートカットはログインの過程をほぼ「Remember Me」クッキーと同じくらい便利に、かつさらなる安全性を実現しています。 一部のブラウザ (OS X の Safari など) では暗号化したグローバルなオペレーティングシステムのキーチェーンにログインのフォームデータを格納します。 ネットワーク環境ではラップトップとデスクトップ間でこのキーチェーンはユーザーと共に移動が可能です。クッキーは通常同期されません。
自動認証での永続的な Remember Me クッキーは広く使用されていますが、 セキュリティ上 不適切です。 ユーザーのログイン名だけを記憶し、 そのユーザー名をログインフォームに入力させる方がはるかに安全です。
デフォルト (安全、 ユーザー名のみ) モードに Remember Me 機能を有効にするために特別な設定は必要ありません。 ログインフォームで Remember Me チェックボックスを rememberMe.enabled にバインドするだけです。次の例をみてください。
<div>
  <h:outputLabel for="name" value="User name"/>
  <h:inputText id="name" value="#{credentials.username}"/>
</div>
  
<div>
  <h:outputLabel for="password" value="Password"/>
  <h:inputSecret id="password" value="#{credentials.password}" redisplay="true"/>
</div>      
  
<div class="loginRow">
  <h:outputLabel for="rememberMe" value="Remember me"/>
  <h:selectBooleanCheckbox id="rememberMe" value="#{rememberMe.enabled}"/>
</div>

15.3.5.1. トークンベースの Remember Me 認証

トークンベースの自動機能 Remember Me を使用するには、 まずトークンストアを設定する必要があります。 この認証トークンは一般的にはデータベース内に格納されます。 Seam はこの方法に対応しますが、 org.jboss.seam.security.TokenStore インターフェースを使って独自のトークンストアを実装することも可能です。本項では JpaTokenStore 実装を使用して認証トークンをデータベーステーブル内に保存することを前提としています。
まず最初にトークンを保持させる新しいエンティティを作ります。以下に可能なエンティティの構造を示します。
@Entity
public class AuthenticationToken implements Serializable {  
  private Integer tokenId;
  private String username;
  private String value;
   
  @Id @GeneratedValue
  public Integer getTokenId() {
    return tokenId;
  }
   
  public void setTokenId(Integer tokenId) {
     this.tokenId = tokenId;
  }
   
  @TokenUsername
  public String getUsername() {
     return username;
  }
   
  public void setUsername(String username) {
    this.username = username;
  }
   
  @TokenValue
  public String getValue() {
    return value;
  }
   
  public void setValue(String value) {
    this.value = value;
  }
}
このコードから分かるように、 エンティティのユーザー名とトークンのプロパティの設定に @TokenUsername@TokenValue という特殊なアノテーションが使われています。 認証トークンを保持するエンティティにはこれらのアノテーションが必要です。
次に、このエンティティ Bean で認証トークンを保管、取得するために JpaTokenStore を設定します。そのために components.xmltoken-class 属性を指定します。
 
<security:jpa-token-store 
     token-class="org.jboss.seam.example.seamspace.AuthenticationToken"/>
最後のステップとして components.xmlRememberMe コンポーネントを設定します。その modeautoLogin に設定してください。
  
<security:remember-me mode="autoLogin"/>
これで Remember Me チェックボックスをチェックしたユーザーは自動的に認証されるようになります。
ユーザーがサイトを再訪した時に確実に自動認証が行われるよう components.xml に以下のセクションを含めてください。
<event type="org.jboss.seam.security.notLoggedIn">
  <action execute="#{redirect.captureCurrentView}"/>
  <action execute="#{identity.tryLogin()}"/>
</event>
<event type="org.jboss.seam.security.loginSuccessful">
  <action execute="#{redirect.returnToCapturedView}"/>
</event>