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.xml
の token-class
属性を指定します。
<security:jpa-token-store token-class="org.jboss.seam.example.seamspace.AuthenticationToken"/>
最後のステップとして
components.xml
に RememberMe
コンポーネントを設定します。その mode
は autoLogin
に設定してください。
<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>