HTTP が独自のセキュリティ モデルを備えた Java ベースのレポート システムにクライアントをリダイレクトする、アクセス制御された PHP システムを使用しています (これはひどいものです)。レポート セキュリティ モデルを回避するために、Tomcat フィルターを使用して、レポート システムに到達する前にすべての要求を検証しています。PHP から Java に渡された暗号化されたトークンを使用しています。これにより、レポート システムにクライアントが誰であるかが通知されます。フィルターは、要求されたレポート名を制限リストと照合してチェックし、クライアントの役割が不十分な場合は 403 を返します。
暗号化されたトークンには、タイムスタンプとユーザーの役割が格納されます。
1365549482|SysAdmin
暗号化するとこんな感じ
vSEFgBYd30Ik5p4PZlG968cvdg==
PHP システムは、すべてのレポート リクエストのプロキシとして機能します。ユーザーがレポートを要求すると、その要求は PHP に送られ、暗号化されたトークンが生成され、URL がエンコードされてレポート URL に追加され、レポート システムに対して GET 要求が行われます。私の Java フィルターはトークンを復号化し、それを引き離し、何をすべきかを判断します。
10 回中 9 回は問題ありませんが、トークンを適切に復号化できない場合があります。上記の(暗号化されていない)例は、次のように変換されます
1365549482q??YZ7
そして、すべてがうまくいかない。
私は暗号化、復号化、および文字エンコーディングの詳細について少し詳しくありませんが、残念ながら、これに取り組むことができる開発者は私だけです。ここで何がうまくいかないのかについての考えは、非常に高く評価されます。ほとんどの場合は機能するため、大きなコードの変更はないと思いますが、時間に敏感なコンポーネントが混在していることは明らかです。以下のコード スニペット
編集
私はこれをデバッグするのにしばらく費やしましたが、それは奇妙になりました。HTTP GET 経由で PHP からトークンを要求する小さな Java プログラムを作成しました。PHP スクリプトは、通常のワークフローで URL パラメーターを介して Java に渡される値と同じ (URL エンコードされた) 値を返します。Java プログラムは、以下のコード スニペットと同じ方法でこれをデコードおよび復号化し、結果を確認します。数千回以上の反復 (これまでのところ、数え切れないほど) が期待どおりに機能しています。ただし、このテストの進行中に、フィルターのログ ファイルで同じエラーが発生していることがわかります。
この断続的な問題の原因は、Tomcat フィルターである Java クラスまたは Tomcat を介して URL で渡されるデータに関連しているようです。これは、ここで何が起こっているのかについてのヒントを誰かに与えますか? 私は今とても混乱しています。
PHP
$presentAsSeconds = time();
$message = strval($presentAsSeconds + Configure::read('Reporting.Authentication.ExpireInSeconds')) . '|' . $userDetails['role'];
return base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
md5(Configure::read('Reporting.Authentication.Key')), // matches "the key" in Java function
$message,
MCRYPT_MODE_CFB,
Configure::read('Reporting.Authentication.IVector') // matches "the vector" in Java function
)
);
ジャワ
private String decrypt(String initial) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(md5("the key").getBytes("UTF-8"), "AES");
IvParameterSpec initialVector = new IvParameterSpec("the vector".getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64()).decode(initial.getBytes("UTF-8"));
byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
return (new String(decryptedByteArray, "UTF8"));
}
private String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes("UTF-8"));
BigInteger number = new BigInteger(1, messageDigest);
return number.toString(16);
}