intra-mart Accel Platform / 認証プログラミングガイド

第2版 2014-04-01

«  概要   ::   コンテンツ   ::   認証プロバイダ・プラグインの開発  »

認証プロバイダ・プラグイン仕様


この章では、認証プロバイダ・プラグインの実装についての説明を行います。
各プロバイダの項では、以下を説明しています。
  • プロバイダのインタフェース
  • intra-mart Accel Platform の標準の認証モジュールで提供する標準実装
  • プロバイダの実装サンプル
ここで紹介するインタフェースや実装サンプルは、一般ユーザ用のものです。
システム管理者用のインタフェースは、システム管理者用インタフェース一覧 を参照してください。

認証プロバイダ・プラグイン一覧

認証機能で提供される認証プロバイダ・プラグインは、以下の通りです。
「対象のテナント」は、リクエスト情報を利用したテナント自動解決機能を利用しない場合の処理対象です。
表 一般ユーザ用認証プロバイダ・プラグイン一覧
プロバイダ名 概要 拡張ポイント 対象のテナント
初期リクエスト解析プロバイダ ログイン画面表示時に送信されたリクエスト情報を解析して、ログイン情報を設定します。 jp.co.intra_mart.security.user.initial_request_analyzer デフォルトテナント
ログインページ・プロバイダ ログイン画面用のページパス情報を取得します。 jp.co.intra_mart.security.user.login_page デフォルトテナント
リクエスト解析プロバイダ ログイン実行時に送信されたリクエスト情報を解析して、ログイン情報を設定します。 jp.co.intra_mart.security.user.login_request_analyzer ログイン時に指定されたテナント
認証条件判定プロバイダ 認証プロバイダを利用するための条件判定を行います。 (認証プロバイダの追加情報として定義) ログイン時に指定されたテナント
認証プロバイダ ログイン情報などを利用して、実際の認証処理を実行します。 jp.co.intra_mart.security.user.certification ログイン時に指定されたテナント
認証リスナ 認証処理の後処理を実行します。 (認証プロバイダの追加情報として定義) ログイン時に指定されたテナント
遷移先ページ・プロバイダ ログイン成功時に遷移する画面のページパス情報を取得します。 jp.co.intra_mart.security.user.target_page ログイン時に指定されたテナント

表 システム管理者用認証プロバイダ・プラグイン一覧
プロバイダ名 概要 拡張ポイント 対象のテナント
初期リクエスト解析プロバイダ ログイン画面表示時に送信されたリクエスト情報を解析して、ログイン情報を設定します。 jp.co.intra_mart.security.administrator.initial_request_analyzer デフォルトテナント
ログインページ・プロバイダ ログイン画面用のページパス情報を取得します。 jp.co.intra_mart.security.administrator.login_page デフォルトテナント
リクエスト解析プロバイダ ログイン実行時に送信されたリクエスト情報を解析して、ログイン情報を設定します。 jp.co.intra_mart.security.administrator.login_request_analyzer デフォルトテナント
認証条件判定プロバイダ 認証プロバイダを利用するための条件判定を行います。 (認証プロバイダの追加情報として定義) デフォルトテナント
認証プロバイダ ログイン情報などを利用して、実際の認証処理を実行します。 jp.co.intra_mart.security.administrator.certification デフォルトテナント
認証リスナ 認証処理の後処理を実行します。 (認証プロバイダの追加情報として定義) デフォルトテナント
遷移先ページ・プロバイダ ログイン成功時に遷移する画面のページパス情報を取得します。 jp.co.intra_mart.security.administrator.target_page デフォルトテナント

認証プロバイダ・プラグイン詳細

初期リクエスト解析プロバイダ

インタフェース定義

  package jp.co.intra_mart.foundation.security.certification.provider;
  
  public interface RequestAnalyzer {
  
     LoginInfo parseRequest(LoginRequestInfo loginInfo, HttpServletRequest request);
  }
第1引数の loginInfo の必要なプロパティを変更して、そのまま返却することを想定しています。

標準実装

初期状態で提供されるプロバイダはありません。

実装サンプル

リクエストパラメータ「sample_home_url」からログイン情報にホームURLを設定するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SampleHomeUrlRequestAnalyzer implements RequestAnalyzer {
    
        @Override
        public LoginInfo parseRequest(LoginRequestInfo loginInfo, HttpServletRequest request) {
    
            // ログイン画面表示時にリクエストパラメータからホームURL情報を設定します。
            String homeUrl = request.getParameter("sample_home_url");
    
            if (homeUrl != null && !homeUrl.isEmpty()) {
    
                // ログイン情報に設定します。
                loginInfo.setHomeUrl(homeUrl);
            }
    
            return loginInfo;
        }
    
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.initial_request_analyzer">
       <initial_request
          name="Sample Initial RequestAnalyzer"
          id="sample.programming_guide.initial_request_analyzer"
          version="1.0"
          rank="200">
    
          <request-analyzer-class>sample.SampleHomeUrlRequestAnalyzer</request-analyzer-class>
    
       </initial_request>
    </extension>
    

引数のログイン情報を要件に合わせて更新し、更新したログイン情報を返却するようにします。 ここで設定した情報は、ログイン画面で保持されてログイン処理に引き継がれます。

プラグインとして設定された順番にプロバイダが実行されます。 順番を考慮した実装および設定を行ってください。

リクエスト解析プロバイダ

インタフェース定義

初期リクエスト解析プロバイダ と同じインタフェースを利用します。

標準実装

実装クラス名(一般ユーザ用)
  • jp.co.intra_mart.system.security.certification.provider.impl.StandardLoginRequestAnalyzer
処理概要
以下の情報をリクエストパラメータから取得してログイン情報に設定します。
  • ユーザコード
  • パスワード
  • 遷移先ページパス

実装サンプル

特定のIPアドレスからアクセスされた場合、パスワードを要求せずに認証済みに設定するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SampleCheckIPAddressRequestAnalyzer implements RequestAnalyzer {
    
        private static final String TRUSTED_ADDRESS = "192.168.108.28";
    
        @Override
        public LoginInfo parseRequest(LoginRequestInfo loginInfo, HttpServletRequest request) {
    
            // アクセスしたクライアントのIPアドレスを取得します。
            String address = request.getRemoteAddr();
    
            if (TRUSTED_ADDRESS.equals(address)) {
    
                // 特定のIPアドレスからアクセスされた場合、認証済みに設定します。
                // パスワード確認処理は行いません。
                // ただし、ユーザコードがない場合、ユーザ情報が取得できないためエラーになります。
                loginInfo.setDoneCertification(true);
            }
    
            return loginInfo;
        }
    
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.login_request_analyzer">
       <login_request
          name="Sample RequestAnalyzer"
          id="sample.programming_guide.request_analyzer"
          version="1.0"
          rank="50">
    
          <request-analyzer-class>sample.SampleCheckIPAddressRequestAnalyzer</request-analyzer-class>
    
       </login_request>
    </extension>
    

引数のログイン情報を要件に合わせて更新し、更新したログイン情報を返却するようにします。 認証で必要な情報は、基本的にここですべてログイン情報に設定してください。

また、サンプルのように認証済み設定を行うことで、認証処理をスキップすることが可能です。 その場合でも認証リスナは実行されます。

プラグインとして設定された順番にプロバイダが実行されます。 順番を考慮した実装および設定を行ってください。

認証プロバイダ

インタフェース定義

  package jp.co.intra_mart.foundation.security.certification.provider;
  
  public interface UserCertification {
  
     CertificationStatus certification(LoginInfo loginInfo, AccountInfo user, HttpServletRequest request, HttpServletResponse response);
  }

標準実装

実装クラス名(一般ユーザ用)
  • jp.co.intra_mart.system.security.certification.provider.impl.StandardUserCertification
処理概要
ログイン情報とアカウント情報のユーザコード、パスワードを比較します。
ユーザコード、パスワードが未設定(null)の場合はエラーとなります。

実装サンプル

ユーザが入力したパスワードからハッシュを作成して、アカウントのパスワードと比較するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SamplePasswordHashUserCertification implements UserCertification {
    
        @Override
        public CertificationStatus certification(LoginInfo loginInfo, AccountInfo user, HttpServletRequest request, HttpServletResponse response) {
    
            // 入力されたパスワードからハッシュを作成します。
            String hash = CryptionUtil.encrypt("account", loginInfo.getPassword());
    
            // ハッシュとアカウントパスワードの比較を行います。
            if (!user.getPassword().equals(hash)) {
                // NGを返却
                return CertificationStatus.CR_NG;
            }
    
            return CertificationStatus.CR_OK;
        }
    
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.certification">
       <certification
          name="Sample UserCertification / UserCertificationValidation / UserCertificationListener"
          id="sample.programming_guide.user_certification"
          version="1.0"
          rank="50">
    
          <!-- UserCertification -->
          <certification-class>sample.SamplePasswordHashUserCertification</certification-class>
    
          <!-- UserCertificationValidation -->
          <certification-validation>
             <validation-class>sample.SamplePasswordHashUserCertificationValidation</validation-class>
          </certification-validation>
    
          <!-- UserCertificationListener -->
          <certification-listener>
             <listener-class>sample.SampleMailAlertUserCertificationListener</listener-class>
          </certification-listener>
    
       </certification>
    </extension>
    

ユーザ情報を検証することで、認証を行います。 認証結果により、以下のコードを返却してください。

表 認証プロバイダの返却コード
返却コード 条件
CertificationStatus.CR_OK 認証に成功した場合
CertificationStatus.CR_NG ユーザ情報が間違っているなどで、認証に失敗した場合
CertificationStatus.CR_ERROR 環境などの要因で、認証が実行できない場合

認証条件判定プロバイダ

インタフェース定義

  package jp.co.intra_mart.foundation.security.certification.provider;
  
  public interface UserCertificationValidation {

     boolean validate(LoginInfo loginInfo, AccountInfo user, HttpServletRequest request, HttpServletResponse response);
  }

標準実装

初期状態で提供されるプロバイダはありません。
該当する認証条件判定プロバイダが存在しない場合、認証プロバイダは常に利用対象となります。

実装サンプル

アカウントのパスワードの暗号化方式として、SHA などのハッシュ方式を利用しているかどうかを確認するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SamplePasswordHashUserCertificationValidation implements UserCertificationValidation {
    
        @Override
        public boolean validate(LoginInfo loginInfo, AccountInfo user, HttpServletRequest request, HttpServletResponse response) {
    
            // システム環境変数からハッシュ暗号化方式をサポートするかを判定します。
            boolean result = Boolean.getBoolean("sample.password.hash.support");
    
            return result;
        }
    
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.certification">
       <certification
          name="Sample UserCertification / UserCertificationValidation / UserCertificationListener"
          id="sample.programming_guide.user_certification"
          version="1.0"
          rank="50">
    
          <!-- UserCertification -->
          <certification-class>sample.SamplePasswordHashUserCertification</certification-class>
    
          <!-- UserCertificationValidation -->
          <certification-validation>
             <validation-class>sample.SamplePasswordHashUserCertificationValidation</validation-class>
          </certification-validation>
    
          <!-- UserCertificationListener -->
          <certification-listener>
             <listener-class>sample.SampleMailAlertUserCertificationListener</listener-class>
          </certification-listener>
    
       </certification>
    </extension>
    

認証プロバイダを利用するための条件を指定します。 認証プロバイダの対応する認証方式がサポートされているかなどを確認します。

認証条件判定プロバイダは、複数設定可能です。
設定されたすべての認証条件判定プロバイダの処理結果が true である場合に、該当の認証プロバイダが利用されます。

認証リスナ

インタフェース定義

  package jp.co.intra_mart.foundation.security.certification.provider;
  
  public interface UserCertificationListener {
  
     void doCertification(CertificationStatus status, LoginInfo loginInfo, AccountInfo user, HttpServletRequest request, HttpServletResponse response);
  }

標準実装

初期状態で提供されるプロバイダはありません。

実装サンプル

ログイン処理の失敗をメール通知するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SampleMailAlertUserCertificationListener implements UserCertificationListener {
    
        @Override
        public void doCertification(CertificationStatus status, LoginInfo loginInfo, AccountInfo user, HttpServletRequest request, HttpServletResponse response) {
    
            if (status != CertificationStatus.CR_OK) {
    
                // 通知メールを作成します。
                StandardMail mail = new StandardMail();
                mail.setFrom("iap@example.com");
                mail.addTo("admin@example.com");
                mail.setSubject("ログイン通知");
                mail.setText("ユーザ:" + loginInfo.getUserCd() + " のログインに失敗しました。");
    
                // 通知メールを送信します。
                MailSender sender = new JavaMailSender(mail);
                try {
                    sender.send();
                } catch (MailSenderException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.certification">
       <certification
          name="Sample UserCertification / UserCertificationValidation / UserCertificationListener"
          id="sample.programming_guide.user_certification"
          version="1.0"
          rank="50">
    
          <!-- UserCertification -->
          <certification-class>sample.SamplePasswordHashUserCertification</certification-class>
    
          <!-- UserCertificationValidation -->
          <certification-validation>
             <validation-class>sample.SamplePasswordHashUserCertificationValidation</validation-class>
          </certification-validation>
    
          <!-- UserCertificationListener -->
          <certification-listener>
             <listener-class>sample.SampleMailAlertUserCertificationListener</listener-class>
          </certification-listener>
    
       </certification>
    </extension>
    

認証の後処理として実行したい、任意の処理を行います。

このプロバイダは、認証処理と同一トランザクションで実行されています。 別トランザクションとする場合は、独自にトランザクションを開始するようにしてください。

ログインページ・プロバイダ

インタフェース定義

  package jp.co.intra_mart.foundation.security.certification.provider;
  
  public interface LoginPageProvider {
  
     PageUrl getLoginPage(LoginInfo loginInfo, HttpServletRequest request, HttpServletResponse response);
  }

標準実装

実装クラス名(一般ユーザ用)
  • jp.co.intra_mart.system.security.certification.provider.impl.StandardUserLoginPageProvider
処理概要
PageManager.getPageUrl() API を利用して、ログインページのパスを取得します。
実際のページパスは、以下に設定されています。
  • クライアントタイプ = PC の場合: plugin/jp.co.intra_mart.certification.page.standard/plugin.xml
  • クライアントタイプ = SP の場合: plugin/jp.co.intra_mart.security.user.login_page.sp/plugin.xml
API の引数に指定するページコードは、jp.co.intra_mart.foundation.security.certification.CertificationPage.LOGIN_PAGE です。

実装サンプル

プラグイン設定ファイルから、ログインページのページパスとリクエストパラメータを取得するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SampleLoginPageProvider implements LoginPageProvider, XmlInitParamable {
    
        private String page;
    
        private Map<String, String> params;
    
        @Override
        public PageUrl getLoginPage(LoginInfo loginInfo, HttpServletRequest request, HttpServletResponse response) {
    
            // ログイン画面表示時にリクエストパラメータからホームURL情報を設定します。
            String custom = request.getParameter("custom");
    
            if (custom != null) {
    
                if (page != null && !page.isEmpty()) {
                    // プラグイン設定ファイルの情報から、ログインページ情報を作成します。
                    PageUrl pageUrl = new PageUrl(page, params);
                    return pageUrl;
                }
    
            }
    
            // 対象外の場合は、その他のプロバイダに移譲します。
            return null;
        }
    
        @Override
        public void init(Node node) {
            // XmlInitParamable を実装することで、プラグイン設定ファイルからノード情報を取得できます。
    
            // プラグイン設定ファイルから、ページパスとリクエストパラメータを取得します。
            XmlNode[] nodes = new XmlNode(node).select("page");
            this.page = nodes[0].getValue();
    
            params = XmlNodeConverter.createInitParamMap(node);
        }
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.login_page">
       <page
          name="Sample LoginPageProvider"
          id="sample.programming_guide.login_page"
          version="1.0"
          rank="200">
    
          <page-provider-class>sample.SampleLoginPageProvider</page-provider-class>
    
          <page>/sample/login.jsp</page>
          <init-param>
            <param-name>foo</param-name>
            <param-value>bar</param-value>
          </init-param>
    
       </page>
    </extension>
    

条件に従ってログインページ情報を、PageUrl オブジェクトに設定します。 設定されたページにはフォワードにより遷移されますが、PageUrl オブジェクトにリクエストパラメータを追加設定することが可能です。

条件に一致しない場合は、null を返却するようにします。 その場合、プラグインとして設定された次のプロバイダに処理が引き継がれます。

遷移先ページ・プロバイダ

インタフェース定義

  package jp.co.intra_mart.foundation.security.certification.provider;
  
  public interface TargetPageProvider {
  
     PageUrl getTargetPage(LoginInfo loginInfo, HttpServletRequest request, HttpServletResponse response);
  }

標準実装

実装クラス名(一般ユーザ用)
  • jp.co.intra_mart.system.security.certification.provider.impl.StandardUserTargetPageProvider
処理概要
以下の順にページ情報を取得します。
  • ログイン情報に遷移先ページ情報が設定されている場合、そのページパスを取得します。
  • セッションにページ情報が設定されてる場合、そのページパスを取得します。
  • 取得できなかった場合、 null を返却します。

実装サンプル

初回ログインユーザに対してウェルカムページを表示するサンプルです。

  • サンプル Java コード

    package sample;
    
    public class SampleWelcomeTargetPageProvider implements TargetPageProvider {
    
        private static final String WELCOME_PAGE = "/welcome";
    
        @Override
        public PageUrl getTargetPage(final LoginInfo loginInfo, final HttpServletRequest request, final HttpServletResponse response) {
    
            // 初回ログインフラグを取得します。
            // 認証リスナ「SampleFirstLoginUserCertificationListener」であらかじめ、リクエストに設定しておきます。
            final String isFirstLoginFlag = (String) request.getAttribute("first_login");
            final boolean isFirstLogin = Boolean.valueOf(isFirstLoginFlag);
    
            if (isFirstLogin) {
                return new PageUrl(WELCOME_PAGE);
            }
    
            // 対象外の場合は、その他のプロバイダに移譲します。
            return null;
        }
    
    }
    
  • サンプルプラグイン設定ファイル

    <extension point="jp.co.intra_mart.security.user.target_page">
       <page
          name="Sample TargetPageProvider"
          id="sample.programming_guide.target_page"
          version="1.0"
          rank="200">
    
          <page-provider-class>sample.SampleWelcomeTargetPageProvider</page-provider-class>
    
       </page>
    </extension>
    

条件に従って遷移先情報を、PageUrl オブジェクトに設定します。 PageUrl オブジェクトは、リクエストパラメータを設定可能で、POSTによる遷移も可能です。

条件に一致しない場合は、null を返却するようにします。 その場合、プラグインとして設定された次のプロバイダに処理が引き継がれます。

標準モジュール認証フロー

intra-mart Accel Platform の標準の認証モジュールでは、4つのプロバイダが提供されています。
標準モジュールで提供されている認証プロバイダ・プラグインによる認証フローは「図 標準認証モジュール認証フロー」のようになります。
この図では、標準モジュールで提供されていないプロバイダは記載していません。
../../_images/certification_flow_standard.png

図 標準認証モジュール認証フロー


システム管理者用インタフェース一覧

表 システム管理者用インタフェース一覧
プロバイダ名 インタフェース
初期リクエスト解析プロバイダ jp.co.intra_mart.foundation.security.certification.provider.RequestAnalyzer (一般ユーザ用と共用)
リクエスト解析プロバイダ jp.co.intra_mart.foundation.security.certification.provider.RequestAnalyzer (一般ユーザ用と共用)
認証プロバイダ jp.co.intra_mart.foundation.security.certification.provider.AdministratorCertification
認証条件判定プロバイダ jp.co.intra_mart.foundation.security.certification.provider.AdministratorCertificationValidation
認証リスナ jp.co.intra_mart.foundation.security.certification.provider.AdministratorCertificationListener
ログインページ・プロバイダ jp.co.intra_mart.foundation.security.certification.provider.LoginPageProvider (一般ユーザ用と共用)
遷移先ページ・プロバイダ jp.co.intra_mart.foundation.security.certification.provider.TargetPageProvider (一般ユーザ用と共用)

«  概要   ::   コンテンツ   ::   認証プロバイダ・プラグインの開発  »