Spring Security 3.0 を使用した AJAX ログインを実行する
search cancel

Spring Security 3.0 を使用した AJAX ログインを実行する

book

Article ID: 341484

calendar_today

Updated On:

Products

VMware

Issue/Introduction

免責事項:これは英文の記事「Performing an AJAX login with Spring Security 3.0 (2002229)」の日本語訳です。記事はベストエフォートで翻訳を進めているため、ローカライズ化コンテンツは最新情報ではない可能性があります。最新の内容については、英語版の記事を参照してください。


多くのアプリケーションでは、Javascript 呼び出しと AJAX 呼び出しを使用してよりインタラクティブな操作をユーザーが体験できるようにしています。この記事には、それらのテクノロジを Spring Security と組み合わせてユーザーを認証するようにアプリケーションを構成する方法が記載されています。

Environment

Spring Framework 2.5
Spring Framework 3.0
Spring Security 2.0
Spring Security 3.0

Resolution

Spring Security、Javascript、および AJAX によってログイン時のユーザー エクスペリエンスを向上させるには、サーバとクライアントの両方で構成を調整する必要があります。これらの調整は、通常の Spring Security ログイン メカニズムに対する機能強化として行い、その強化されたログイン プロセスと並行して通常のフォームベースのログインも引き続き機能するようにします。

サーバ側での変更

:これらの調整は、Spring MVC ベースのアプリケーションに対して行う必要があります。

Spring Security のインストールと設定
Spring Security をインストールして設定するには、次の手順を実行します。
  1. Spring Security の依存関係を追加します。

    依存関係の管理に Maven または Ant を使用する場合は、それらの依存関係を追加します。最初の 2 つの依存関係 spring-security-web および spring-security-config は必須です。最後の依存関係 spring-security-taglibs は任意ですが、JSP ページを使用する場合には追加することをお勧めします。

    <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>3.0.5.RELEASE</version>
    <type>jar</type>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>3.0.5.RELEASE</version>
    <type>jar</type>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>3.0.5.RELEASE</version>
    <type>jar</type>
    <scope>compile</scope>
    </dependency>

  2. web.xml ファイルを編集します。

    このフィルタ定義を追加することにより、Spring Security のフィルタを追加します。これにより通常は、フィルタ チェーンのリストの先頭にフィルタが追加されます(まず web.xml に追加します)。Spring Security をフィルタ チェーンの先頭に追加し、後続のフィルタが Spring Security によって保護されるようにすることをお勧めします。

    <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

Spring Security の構成

Spring Security を構成するには、次の手順を実行します。
  1. Spring bean 構成ファイルをプロジェクトに追加します。これには、Spring Security の構成が含まれています。
  2. 新しく追加した Spring bean 構成ファイルの先頭に、次の行を追加します。

    <http>
    <form-login>
    <logout />
    <remember-me />
    <intercept-url pattern="/resources/**" filters="none" />
    <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <intercept-url pattern="/secure" access="ROLE_USER" />
    <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    </http>

    </form-login>
    これにより、標準のフォームベース ログインを使用するように Spring Security 自体を構成し、「ユーザー名を記憶」をサポートするよう、Spring Security に指示します。さらに、構成によっていくつかの <intercept-url/> タグが追加されます。これらのタグは、それぞれ指定された URL で必要とされるアクセス権を定義するために使用されます。上記の構成では、次の URL が定義されます。

    • /resources/** には、イメージ、CSS、および Javascript などの静的ファイルが含まれています。これは、Spring Security によって処理されません。
    • / と /login は、ランディング ページとログイン ページです。これらのページはどちらも Spring Security によって処理されますが、アクセス権限が不要なため、未認証のユーザーもこれらのリソースにアクセスすることができます。
    • /secure は「保護された」リソースです。このサンプル アプリケーションには、「保護された」リソースが 1 つだけ含まれています。ただし、より全機能に近いアプリケーションには多くのリソースが存在し、通常はワイルドカードで指定されています。この URL も Spring Security によって処理され、ROLE_USER 権限を必要とします。

      :上記の <INTERCEPT-URL></INTERCEPT-URL>タグは、各アプリケーションの要件に適合するようにカスタマイズする必要があります。上記の一覧にあるタグは、サンプル アプリケーションに固有の基本的なタグの例です。

  3. Spring Security 構成ファイルの <http/> タグの後に、次の行を追加します。

    <authentication-manager alias="authenticationManager">
    <authentication-provider>
    <user-service>
    <user name="frank" password="1234" authorities="ROLE_USER" />
    </user-service>
    </authentication-provider>
    </authentication-manager>


    これにより、ユーザーの認証に使用される簡易なメモリ内認証マネージャを作成するよう Spring Security に指示します。メモリ内サービスには、パスワードを 1234 とするユーザー frank が 1 つ含まれています。

    :添付された例の場合はこのメモリ内ソリューションで十分ですが、本番環境のデプロイでは推奨されるアプローチではありません。本番環境のシナリオでは、JDBC または LDAP によってバッキングされる認証マネージャで置き換えるようお勧めします。
アクティブな Spring Security の構成および検証
アクティブな Spring Security 構成を構成および検証するには、次の手順を実行します。
  1. 使用アプリケーションのルート アプリケーション コンテキストとしてロードされている構成ファイルを見つけます。これは、ContextLoaderListener によってロードされる Spring bean 構成ファイルか、Spring bean Java クラスです( web.xml で構成)。

  2. 以前に作成された Spring Security 構成ファイルをインポートするように、ルート アプリケーションのコンテキストを編集します。

    ルート アプリケーションのコンテキストが XML で定義されている場合、import 行は次のようになります。

    <import resource="security.xml" />

    ルート アプリケーションのコンテキストが Java クラスで定義されている場合、import 行は次のようになります。

    @ImportResource("security.xml")

  3. この時点で、Spring Security は標準のフォームベース認証で完全に構成されている必要があります。残りのインストール処理を続行する前に、ここまでのすべての設定が正しく構成されていることをテストすることは重要です。

    このテストを行うには、アプリケーションをデプロイし、セキュリティで保護されているリソースへのアクセスを試みます。正しく構成されていれば、Web ブラウザが簡単なログイン フォームにリダイレクトされます。ログイン名 ( frank) およびパスワード (1234) を入力します。ログインが正常に完了し、ブラウザがセキュリティで保護されているリソースにリダイレクトされれば、アプリケーションは正常に機能しています。

    例外が発生した場合は、この記事の前のセクションに戻り、誤りがないかどうか調べてください。

セキュリティ コントローラの作成と検証
セキュリティ コントローラを作成および検証するには、次の手順を実行します。
  1. AjaxLoginController という新しいコントローラを作成します。このコントローラにより、ログイン フォームを HTML フラグメントとして表示し、フォームが送信されるときの AJAX POST 要求を処理します。

    クラスは次のようになります。

    @Controller
    @RequestMapping("/login")
    public class AjaxLoginController {
    @Autowired
    @Qualifier("authenticationManager")
    AuthenticationManager authenticationManager;

    @Autowired
    SecurityContextRepository repository;

    @Autowired
    RememberMeServices rememberMeServices;

    @RequestMapping(method=RequestMethod.GET)
    public void login() {}

    @RequestMapping(method=RequestMethod.POST)
    @ResponseBody
    public String performLogin(
    @RequestParam("j_username") String username,
    @RequestParam("j_password") String password,
    HttpServletRequest request, HttpServletResponse response)
    {
    UsernamePasswordAuthenticationToken token =
    new UsernamePasswordAuthenticationToken(username, password);
    try {
    Authentication auth = authenticationManager.authenticate(token);
    SecurityContextHolder.getContext().setAuthentication(auth);
    repository.saveContext(SecurityContextHolder.getContext(), request, response);
    rememberMeServices.loginSuccess(request, response, auth);
    return "{\"status\": true}";
    } catch (BadCredentialsException ex) {
    return "{\"status\": false, \"error\": \"Bad Credentials\"}";
    }
    }
    }

    • このクラスには @RequestMapping(“/login”) という注釈が付きます。この注釈により、Spring に対して、 /login をこのコントローラに経路指定するよう要求されていることが通知されます。この URL が Spring Security 構成の < intercept-url /> <INTERCEPT-URL></INTERCEPT-URL>タグ内にリストされており、その <INTERCEPT-URL></INTERCEPT-URL>タグが URL への匿名アクセスを許可するように構成されていることは重要です。そのように構成されていないと、未認証のユーザーはログイン フォームを表示できません。
    • Spring Security のリソースは、AuthenticationManagerSecurityContextRepository、および RememberMeServices クラスに自動接続されます。これらのリソースは、実際のログイン処理を実行するために AjaxLoginController が使用します。
    • ログイン機能は GET 要求に対する応答として呼び出されます(つまり、ユーザーがログイン フォームを要求します)。これによる処理は何も行われず、ビューが表示されます。ビューには、HTML フラグメントを Javascript によって受信し、おそらく Javascript ダイアログ ボックスを使用してすでに存在する HTML ドキュメントに挿入できるよう、ログイン フォームが(完全な HTML ページではなく) HTML フラグメントとして返されます。
    • performLogin 関数は、POST 要求に対する応答として呼び出されます(つまり、ユーザーのログイン試行)。この関数では、挿入されたサービスを使用してユーザーを認証します。ユーザーが正常に認証されると、その認証オブジェクトが保存され、「ユーザー名を記憶」サービスに渡されます。応答として、簡単な JSON 文字列が返されます。

  2. コントローラをアプリケーションの Spring MVC 構成に追加します。通常これは、コントローラが、コンポーネント スキャンによって検索(つまり、< context:component-scan />)されるパッケージ内に確実に配置されるようにすることを意味します。ただし、アプリケーションの構成によっては、コントローラの bean を手動で定義することが必要になる場合もあります(たとえば、アプリケーションでコンポーネント スキャンを使用しない場合)。

  3. GET および POST の両方で、 AjaxLoginController の可用性をテストします。

    GET 要求を検証するには、Web ブラウザを開いて http://localhost:8080/login に移動します。これにより、ログイン フォームの HTML フラグメントが表示されます(完全な HTML ページではないため、異常のように見える可能性があります)。

    HTML フラグメントが表示されず、代わりにデフォルトの Spring Security ログイン フォームが表示される場合は、Spring Security の構成を調べ、未認証のユーザーも /login URL にアクセスできるようになっている(つまり、アクセス権が IS_AUTHENTICATED_ANONYMOUSLY に設定されている)ことを確認してください。

    POST 要求を検証するには、cURL のようなツールを使用して要求を http://localhost:8080/login に POST します。このコマンドにより、POST 要求が実行され、JSON 応答が返されます。JSON 応答が正常なことを検証します。

    curl -d "j_username=frank" -d "j_password=1234" http://localhost:8080/appName/login

    コントローラを検証する場合は、クライアントの構成に進みます。


クライアント構成

クライアント側で必要とされる構成は、HTML および Javascript で実行されます。HTML 部分はいくつかの標準 HTML フォームで構成されています。Javascript コードは、アプリケーションで使用するよう選択する特定の Javascript ライブラリ(または、ライブラリの不足)によって決まります。そのためこのセクションでは、実際の実装ではなく、クライアント側を構成するために必要とされるタスクに焦点をあてます。具体的な詳細については、HTML と jQuery が使用されているサンプル アプリケーションを参照してください。
  1. ランディング ページを定義します。これは、未認証ユーザーの最初の移動先で、そのページでログイン リンクをクリックします。サンプル アプリケーションの場合、これは / url です。

  2. ログイン フォームを定義します。これは、ユーザーがログイン リンクをクリックすると表示されます。これは、フォームの単なる HTML フラグメントです。ほとんどの場合、ログイン フォームは「ダイアログ」ボックスで表示されます。このフォームを表示するために使用される実際の方法は、アプリケーションとアプリケーションが使用する Javascript ライブラリによって決まります。

    サンプル アプリケーションの場合、これは /login url であり、jQuery ダイアログ ボックスに表示されます。

  3. ユーザーのログイン試行を処理する Javascript コードを記述します。

    このプロセスは、次の手順に分割されます。

    1. ユーザーがログイン リンクをクリックする場合は、Javascript を使用して GET 要求を AjaxLoginController's ログイン メソッドに送信します。これにより、HTML フラグメントとしてログイン フォームが返されます。このフォームは、

      タグ内か「ダイアログ」ボックス内部に容易に配置できます。

    2. ユーザーが認証情報をフォームに入力して [ログイン] ボタンをクリックする場合は、フォーム データを収集し、Javascript を使用して POST 要求を AjaxLoginController's performLogin メソッドに送信します。このメソッドからの応答は、ユーザーが正常に認証されたかどうかを示す JSON メッセージです。

    3. JSON 応答を解析し、ログインの試行に成功したかどうかを判別します。ログインに失敗した場合は、ユーザーに理由を表示します。理由は、エラー プロパティとして JSON 応答に含まれています。ログインに成功した場合は、ダイアログを閉じ、アプリケーションに現在ログインしていることを示すアラートをユーザーに表示します。

      :両方の側がフォーマットについて同意する場合は、 AjaxLoginController's performLogin メソッドと Javascript ログイン プロセスの間で交換される JSON データをカスタマイズすることが可能です。

  4. ログアウトするには、ユーザーを /j_spring_security_logout URL に転送します。これには、 タグを使用するか、Javascript を使用して GET 要求を同じ URL に送信します。

サンプル アプリケーション

この記事には、サンプル アプリケーションが添付されています ( 2002229_SpringSecutiryAjaxDemo.zip)。このアプリケーションは Maven を使用して作成することができ、 mvn tomcat:run コマンドによって実行できます。

これにより、サンプル アプリケーションが URL ( http://localhost:8080/ajax-login/) にデプロイされます。この URL にアクセスすると、アプリケーションのランディング ページが表示されます。標準ログインリンクをクリックすると、標準の Spring Security ログインのワークフローが開始されます。Ajax ログインリンクをクリックすると、強化された Spring Security ログインのワークフローが開始されます。

サンプル アプリケーションは、Spring MVC、Spring Security、および jQuery を使用して開発されています。上の説明にあるプロセスの詳細については、添付されているサンプル アプリケーションを参照してください。


Additional Information

: Spring Framework および Spring Security はフレキシブルであり、特有のニーズを満たすようにタスクを構成することができます。この記事に示されている解決策は考えられる解決策の 1 つであり、「目的」セクションで説明されている要件を満たします。ニーズはそれぞれのユーザーで異なるため、この記事に示されている構成またはコードは実際のニーズに適合するように調整する必要が生じる可能性があります。

この記事に記載されている構成や、ニーズに合うように調整することに関してサポートが必要な場合は、「Spring Security Forum」でスレッドを開始してください。Performing an AJAX login with Spring Security 3.0