機能説明

CSRF対策用のSecureTokenを出力するタグです。
formタグ用にhiddenタグを生成します。

SecureTokenとは?

データを登録するためのURLや、ログイン処理を実行するためのURLに直接アクセスし、不正な処理の要求を防ぐための技術です。
SecureTokenでは、正規の手順を辿っているアクセスに対して実行を許可し、そうではない不正なアクセスをブロックします。


リクエストが正規の手順で実行されているかどうかの判定は、対象のページより前にアクセスする画面でアクセスしたことを示すトークンを発行することで判定します。

  1. サーバは正規のアクセスに対しトークンを発行し、クライアントに送信します。トークンはセッションに保存しておきます。
  2. クライアントは、サーバから受け取ったトークンをリクエストパラメータに入れて次の画面にアクセスする要求をします。
  3. サーバはセッションに保存したトークンと、リクエストで送信されたトークンを比較します。トークンが一致すれば、正規なアクセスなのでアクセスを許可します。
  4. トークンが一致しない、または、トークン自体を送信してこないアクセスは、正規手順ではないアクセスなのでアクセスを許可しません。


トークンを発行する画面を経由しないアクセスは、不正なアクセスと見なして遮断することができます。
具体的には、以下のようなリクエストを遮断することができます。

  • ログイン画面を表示していないのに、ログイン処理URLにアクセスされた場合。
  • 登録情報入力画面を表示していないのに、登録処理URLにアクセスされた場合。

AjaxでSecureTokenを使いたいときは?

Ajaxでアクセスする先に送信するためのトークンを取得したい場合、mode属性を指定してトークンを生成します。
ただし、mode属性を使用できるのはバージョン 8.0.8 以降です。
バージョン 8.0.8 より前の場合、このタグは使用せずに SecureTokenManager を使用します。
APIの使用方法は、APIドキュメントを参照してください。

SecureToken対象ページの設定方法は?

設定ファイルに対象URLを記述する方法と、対象ページの先頭にベリファイ処理を実装する方法があります。
設定ファイルについては、設定ファイルリファレンス の「セキュア・トークンフィルタ設定」を参照してください。
http://www.intra-mart.jp/document/library/iap/public/configuration/im_configuration_reference/texts/im_tenant/token-filtering-target-config/index.html

  • 原則、設定ファイルにURLを記述することをおすすめします。
  • 「対象ページの先頭にベリファイ処理を実装する方法」は、対象URLが動的であるなどの理由で設定ファイルに記述できない場合でも利用可能です。
  • セッションタイムアウトなどでセッションが破棄されると、トークンが無効化されます。

属性一覧

注釈 属性名 説明 省略時の動作
mode String バージョン 8.0.8 以降で利用可能です。
mode属性に指定した値により、タグが出力する内容が異なります。
“tag”,“name”,“value” のいずれかを指定します。
  • “tag” : セキュア・トークンを出力したhiddenタグを出力します。
  • “name” : セキュア・トークンのリクエストパラメータ名を出力します。(SecureTokenManager.REQUEST_PARAMETER_NAMEの値)
  • “value” : セキュア・トークンそのものを出力します。
tag
Boolean属性 useOneTimeToken String/boolean このトークンを1回使用した時点で無効化するかを指定します。 false
その他 String トークンを生成するシードに含めるキーと値を指定します。
トークンのベリファイ時、リクエストパラメータに同じキーと値が含まれている必要があります。
-

サンプル

SecureTokenの最低限の実装

リクエスト元とリクエスト先のhtmlとjsを実装します。
  • この例では、sample/csrf1とsample/csrf2のhtmlとjsを作成します。
  • jsファイルは、空のファイルを作成します。
リクエスト元のHTMLにはHTMLサンプルのようにSecureTokenタグを配置します。



ルーティングとSecureTokenの設定ファイルを記述します。



“/sample/csrf1”にアクセスし、サブミットボタンをクリックすると“/sample/csrf2”に画面遷移します。



ブラウザのアドレスバーには以下のようなアドレスが表示されています。
  • ~/sample/csrf2?im_secure_token=172879d058f5f4b1d0ff715fbc615e749ccead40bbc87d719f0b6d4196cd62be
この状態で、アドレスバーでエンターキーを押しても“sample/csrf2”の画面が表示されます。



次に、“?im_secure_token=~”の部分を削除してエンターキーを押してみます。

403エラー画面が表示されれば、SecureTokenの最低限の実装が完了です。
HTML (sample/csrf1.html)
<form action="sample/csrf2" method="GET">
  <imart type="imSecureToken" />
  <input type="submit" value="send" />
</form>
HTML (sample/csrf2.html)
Success!
ルーティング設定ファイル (conf/routing-jssp-config/sample-im_csrf.xml)
<?xml version="1.0" encoding="UTF-8"?>
<routing-jssp-config xmlns="http://www.intra-mart.jp/router/routing-jssp-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/router/routing-jssp-config routing-jssp-config">
  <authz-default mapper="welcome-all"/>
  <file-mapping path="/sample/csrf1" page="sample/csrf1"/>
  <file-mapping path="/sample/csrf2" page="sample/csrf2"/>
</routing-jssp-config>
セキュア・トークンフィルタ設定ファイル (conf/token-filtering-target-config/im_csrf_sample.xml)
<?xml version="1.0" encoding="UTF-8"?>
<token-filtering-target-config xmlns="http://www.intra-mart.jp/secure-token/target-url-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/secure-token/target-url-config ../../schema/token-filtering-target-config.xsd ">
  <entry url="/sample/csrf2" />
</token-filtering-target-config>

ワンタイムトークンの利用

最低限の実装例に、ワンタイムトークンを使うように指定します。



“/sample/csrf1”にアクセスし、サブミットボタンをクリックすると“/sample/csrf2”に画面遷移します。



ブラウザのアドレスバーには以下のようなアドレスが表示されています。
  • ~/sample/csrf2?im_secure_token=172879d058f5f4b1d0ff715fbc615e749ccead40bbc87d719f0b6d4196cd62be
この状態で、アドレスバーでエンターキーを押すと、403エラー画面が表示されます。



既に使用したトークンなので、再度“/sample/csrf1”にアクセスしてトークンを発行するまでは“/sample/csrf2”の画面にはアクセスできなくなります。
HTML (sample/csrf1.html)
<form action="sample/csrf2" method="GET">
  <imart type="imSecureToken" useOneTimeToken="true" />
  <input type="submit" value="send" />
</form>

AjaxでSecureTokenを使う(バージョン 8.0.8 以降)

AjaxでSecureTokenを使用する例です。


リクエスト元のページでタグにmode属性を指定してトークンを作成します。
作成したトークンは、Ajaxのパラメータに含めます。
HTML (sample/csrf3.html)
<script type="text/javascript">
(function ($) {
  $(function () {
    $('#send').click(function () {
      $.ajax({
        'url': 'sample/csrf4',
        'data': {
          '<imart type="imSecureToken" mode="name" />': '<imart type="imSecureToken" mode="value" />',
          'no-theme': 'true'
        },
        'success': function (data) {
          $('<div></div>').appendTo(document.body).append(data).dialog();
        }
      });
    });
  });
})(jQuery);
</script>

<input type="button" id="send" value="send" />
HTML (sample/csrf4.html)
Hello CSRF!
ルーティング設定ファイル (conf/routing-jssp-config/sample-im_csrf.xml)
<?xml version="1.0" encoding="UTF-8"?>
<routing-jssp-config xmlns="http://www.intra-mart.jp/router/routing-jssp-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/router/routing-jssp-config routing-jssp-config">
  <authz-default mapper="welcome-all"/>
  <file-mapping path="/sample/csrf3" page="sample/csrf3"/>
  <file-mapping path="/sample/csrf4" page="sample/csrf4"/>
</routing-jssp-config>
セキュア・トークンフィルタ設定ファイル (conf/token-filtering-target-config/im_csrf_sample.xml)
<?xml version="1.0" encoding="UTF-8"?>
<token-filtering-target-config xmlns="http://www.intra-mart.jp/secure-token/target-url-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/secure-token/target-url-config ../../schema/token-filtering-target-config.xsd ">
  <entry url="/sample/csrf4" />
</token-filtering-target-config>

AjaxでSecureTokenを使う(バージョン 8.0.7 以前)

AjaxでSecureTokenを使用する例です。


リクエスト元のページでAPIを使用してトークンを作成します。
作成したトークンは、Ajaxのパラメータに含めます。
HTML (sample/csrf5.html)
<script type="text/javascript">
(function ($) {
  $(function () {
    $('#send').click(function () {
      $.ajax({
        'url': 'sample/csrf6',
        'data': {
          '<imart type="string" value=bind.name />': '<imart type="string" value=bind.value />',
          'no-theme': 'true'
        },
        'success': function (data) {
          $('<div></div>').appendTo(document.body).append(data).dialog();
        }
      });
    });
  });
})(jQuery);
</script>

<input type="button" id="send" value="send" />
HTML (sample/csrf5.js)
var bind = {};

function init(request) {
  bind.name = SecureTokenManager.REQUEST_PARAMETER_NAME;

  var result = new SecureTokenManager(request).createToken(false);
  if (!result.error) {
    bind.value = result.data;
  } else {
    bind.value = '';
  }
}
HTML (sample/csrf6.html)
Hello CSRF!
ルーティング設定ファイル (conf/routing-jssp-config/sample-im_csrf.xml)
<?xml version="1.0" encoding="UTF-8"?>
<routing-jssp-config xmlns="http://www.intra-mart.jp/router/routing-jssp-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/router/routing-jssp-config routing-jssp-config">
  <authz-default mapper="welcome-all"/>
  <file-mapping path="/sample/csrf5" page="sample/csrf5"/>
  <file-mapping path="/sample/csrf6" page="sample/csrf6"/>
</routing-jssp-config>
セキュア・トークンフィルタ設定ファイル (conf/token-filtering-target-config/im_csrf_sample.xml)
<?xml version="1.0" encoding="UTF-8"?>
<token-filtering-target-config xmlns="http://www.intra-mart.jp/secure-token/target-url-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/secure-token/target-url-config ../../schema/token-filtering-target-config.xsd ">
  <entry url="/sample/csrf6" />
</token-filtering-target-config>

SecureToken設定ファイルなしで、AjaxでSecureTokenを使う

SecureTokenの設定ファイルを書かずに、AjaxでSecureTokenを使用する例です。


リクエスト元のページでAPIを使用しトークンを作成します。
作成したトークンは、Ajaxのパラメータに含めます。


Ajaxでリクエストされるページでは、APIを使用してベリファイ処理を実装します。
HTML (sample/csrf7.html)
<script type="text/javascript">
(function ($) {
  $(function () {
    $('#send').click(function () {
      $.ajax({
        'url': 'sample/csrf8',
        'data': {
          '<imart type="string" value=bind.name />': '<imart type="string" value=bind.value />',
          'no-theme': 'true'
        },
        'success': function (data) {
          $('<div></div>').appendTo(document.body).append(data).dialog();
        }
      });
    });
  });
})(jQuery);
</script>

<input type="button" id="send" value="send" />
JS (sample/csrf7.js)
var bind = {};

function init(request) {
  bind.name = SecureTokenManager.REQUEST_PARAMETER_NAME;

  var result = new SecureTokenManager(request).createToken(false);
  if (!result.error) {
    bind.value = result.data;
  } else {
    bind.value = '';
  }
}
HTML (sample/csrf8.html)
Hello CSRF!
JS (sample/csrf8.js)
function init(request) {
  let response = Web.getHTTPResponse();
  if(!new SecureTokenManager().verify().data){
    // エラー処理
    response.sendError(403);
  }
  response.setContentType('text/plain; charset=utf-8');
}
ルーティング設定ファイル (conf/routing-jssp-config/sample-im_csrf.xml)
<?xml version="1.0" encoding="UTF-8"?>
<routing-jssp-config xmlns="http://www.intra-mart.jp/router/routing-jssp-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.intra-mart.jp/router/routing-jssp-config routing-jssp-config">
  <authz-default mapper="welcome-all"/>
  <file-mapping path="/sample/csrf7" page="sample/csrf3"/>
  <file-mapping path="/sample/csrf8" page="sample/csrf4"/>
</routing-jssp-config>