残念ながら、アプリケーションがロード済みの署名付き jar マニフェストにアクセスする必要がある場合、7 update 45 の問題を回避するために Oracle および他のユーザーが提供する回避策 ( Java アプレット マニフェスト - すべての Caller-Allowable-Codebase を許可する) は機能しません。私の場合、アプリは関連するマニフェスト情報をログに記録するためにこれを行います。
私の Web Start アプリでは、7u21 用に追加する必要がある「Trusted-Library」属性を使用して、すべてがうまく機能しました。7u45 では、「Trusted-Library」属性を削除し、他の回避策で説明されているすべての追加属性を追加しても機能しません。Trusted-Library 属性なしで 7u21 を実行した場合と同じ警告が表示されます (アプリケーションに署名済みコードと未署名コードの両方が含まれていることを示す):
私は可能な限りすべてのマニフェスト/JNLP 順列を試しましたが、完璧なものは何もありません。
私が見つけたのは、基本的に、アプレットの jar マニフェスト (JRE jar ではない) の 1 つをロードし、hasMoreElements を呼び出すと、警告をトリガーする追加のセキュリティ チェックが発生することです。
public List<String> getManifests() {
...
Enumeration<URL> urls = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
while (urls.hasMoreElements()) {
.... a bunch of loop stuff
// at the end of the loop...
System.out.println("Checkpoint SGMLOOP8.");
System.out.println("Breaking....");
//break; <<<<<<---- if the next jar is one of our signed jars, the next line will trigger the warning. If instead we choose to break, the app works perfectly with no warning.
System.out.println("urls.hasMoreElements(): " + (urls.hasMoreElements() ? "true" : "false")); <<<<<<-------- will evaluate to false if user clicks Block on the warning, otherwise will evaluate to true when our signed jars are next
System.out.println("Checkpoint SGMLOOP9.");
}
...
}
これは、最大トレースで Java コンソールに出力されるものです。
Checkpoint SGMLOOP8.
Breaking.... <<<<---- console output pauses here until user answers warning
security: resource name "META-INF/MANIFEST.MF" in http://<path_to_jar> : java.lang.SecurityException: trusted loader attempted to load sandboxed resource from http://<path_to_jar>
(message repeats for all our signed jars)
urls.hasMoreElements(): false <<<<---- false because user clicked blocked, otherwise true when user clicks don't block
Checkpoint SGMLOOP9.
これを理解するのに永遠にかかりました。なぜなら、何らかの理由で、起動プロセスの早い段階でセキュリティチェックに合格し、その後アクセスされて不平を言われる署名付きマニフェストがマニフェストについて不平を言っているとは思わないからです。むしろ、マニフェストによって参照されるリソースです。図に行く!
Java ソース コードを調べると、警告が発生する可能性がある理由がわかります (hasMoreElements は、より多くのセキュリティ チェックにつながります)。
// getResources is called in my code above
java.lang.ClassLoader
public Enumeration<URL> getResources(String name) throws IOException {
Enumeration[] tmp = new Enumeration[2];
if (parent != null) {
tmp[0] = parent.getResources(name);
} else {
tmp[0] = getBootstrapResources(name);
}
tmp[1] = findResources(name); <<<<------ This returns a new Enumeration<URL> object which has its own “hasMoreElments()” method overwritten – see below code
return new CompoundEnumeration<>(tmp);
}
java.net.URLClassLoader
public Enumeration<URL> findResources(final String name)
throws IOException
{
final Enumeration<URL> e = ucp.findResources(name, true);
return new Enumeration<URL>() {
private URL url = null;
private boolean next() {
if (url != null) {
return true;
}
do {
URL u = AccessController.doPrivileged( <<-- Security context could block this
new PrivilegedAction<URL>() {
public URL run() {
if (!e.hasMoreElements())
return null;
return e.nextElement();
}
}, acc);
if (u == null)
break;
url = ucp.checkURL(u); <<-- Security checks done in here
} while (url == null);
return url != null;
}
public URL nextElement() {
if (!next()) {
throw new NoSuchElementException();
}
URL u = url;
url = null;
return u;
}
public boolean hasMoreElements() {
return next();
}
};
}
はい、マニフェストは適切に署名されています! はい、マニフェストには適切な属性があります! 実際、これは、マニフェストに直接アクセスしようとしない限り、jar が正常にロードされて実行されるという事実によって証明されています。ただし、懸念を和らげるために、関連するマニフェスト属性を次に示します (以下の属性の多くの追加/削除を試みました)。
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 24.45-b08 (Oracle Corporation)
Application-Name: AppName
Codebase: *
Permissions: all-permissions
Application-Library-Allowable-Codebase: *
Caller-Allowable-Codebase: *
Trusted-Only: false
Class-Path: jar1.jar jar2.jar jar3.jar
Specification-Title: AppName
Specification-Version: 1.0
Specification-Vendor: CompanyName
Implementation-Title: AppName
Implementation-Version: 1.0
Implementation-Vendor: CompanyName
問題は、マニフェストにアクセスしようとしたときに警告が発生する必要があるかどうかです。現状では、ユーザーに毎回警告を強制的に表示するか、署名済みの jar マニフェスト情報のログを削除するかのいずれかを選択する必要があります。特に、このマニフェスト情報は問題のデバッグに非常に役立つため、エンドユーザーが正しいバージョンのアプリを実行していることを確認する唯一の方法であるため (オンサイトでの直接の物理的な検査を除く)、悪い選択のように思えます。jar は (アプレットにアクセスするための対応する JavaScript と共に) クライアント システムにキャッシュされることが許可されているため、これはアプレットに特に当てはまります。ログの情報は、将来大きな頭痛の種になる可能性があります。
何か案は?Oracle は Trusted-Library の問題をいずれにせよ修正しようとしているので、これは特に苛立たしいことです。そのため、このすべての調査作業をこれに費やすことは、私の週末を無駄にすることに他ならないかもしれません。ぐぅ……
編集:私が観察したことの 1 つは、セキュリティ例外に遭遇した最初の jar が、実際にはアプリ内の別の jar に依存していたことです。「依存する jar のマニフェストを最初に読み込む必要があるのではないか」と考えました。そのため、依存しないjarが最初にロードされるように、ロード順序を強制しました。最終結果?非依存の jar が最初にセキュリティ例外をスローしたことがわかりました...そしてまだ警告があります。