21

Java で 'final' キーワードを使用する理由はたくさんありますが、私が何度も耳にする理由の 1 つは、コードがより安全になるということです。これは、この些細なケースでは理にかなっているように見えますが:

public class Password
{
    public final String passwordHash;
    ...
}

final キーワードを使用すると、悪意のあるコードが変数 passwordHash を変更できないことが予想されます。ただし、リフレクションを使用すると、passwordHash フィールドの final 修飾子を変更できます。

それでは、「最終」は本当のセキュリティを提供しますか、それとも単なるプラセボですか?

編集: いくつかの非常に興味深い議論があり、複数の回答を受け入れることができればいいのにと思います. ご意見をお寄せいただきありがとうございます。

4

12 に答える 12

39

「攻撃に耐える」という意味での「セキュリティ」ではありません。それは「誤って台無しにするのが難しい」ようなものです。

「安全」という言葉は、悪意ではなく、事故を防ぐようなものだと思うので、私は好きです。

于 2010-01-21T18:40:27.117 に答える
11

Java のfinalキーワードは、この種のセキュリティには使用されません。これは、通常暗号化ソリューションを必要とするものに代わるものではありません。

この種の議論で通常「セキュリティ」が意味するのは、安全なオブジェクト モデルの概念です。つまり、クラスの元の作成者が意図しない目的で消費者が操作できないオブジェクト モデルです。

于 2010-01-21T18:37:35.607 に答える
8

システムのセキュリティを強化するために言語構造に依存するかどうかはわかりません。

フィールドを final にすることで、悪意のある攻撃に対するセキュリティが強化されるとは思いません (間違いや、もちろんスレッド化の問題に対する可能性が高くなります)。セキュリティの唯一の「実際の形式」は、 final 定数フィールドがある場合、コンパイル時にインライン化される可能性があるため、実行時にその値を変更しても影響がないことです。

継承のコンテキストでは、ファイナルとセキュリティについてもっと聞いたことがあります。クラスを final にすることで、誰かがそれをサブクラス化し、その保護されたメンバーに触れたりオーバーライドしたりするのを防ぐことができますが、これも脅威を防ぐためというよりも、間違いを避けるために使用します。

于 2010-01-21T18:41:07.747 に答える
4

一般に、最終的に、プライベートおよびその他のそのような構成は、厳密に強制されたセキュリティではなく、一般的な好みのステートメントと見なす必要があります。

ただし、プロセスが実行されているJVMを制御する場合(たとえば、JVMで他のユーザーから提供されたコードを実行する場合)、finalおよびprivateは、JavaのSecurityManagerと組み合わせて実際にセキュリティを提供します。これらの制限を回避するためにリフレクションを介して実行できることを防ぐことができます。

あなたができないことは、他の誰かのJVMで実行するコードを出荷し、この方法で何かを隠すと考えることです。

編集:トムは、シリアル化攻撃(つまり、シリアル化されたデータの不正なバイナリストリームを意図的に提供する)も、finalフィールドを適切に使用することで部分的に防ぐことができることを思い出させます。効果的なJavaには、そのような例がさらにあります。

于 2010-01-21T18:44:34.933 に答える
4

何に対して安全ですか?

モバイル コード (システム間を移動できるコード - アプレット、ミッドレット、WebStart、RMI/JINI など) に関しては、非常に重要です。クラスに適用され、アクセス可能なメソッドの程度は低く、悪意のある実装を防ぎます。アクセス可能なフィールドと同様に、注目すべき静的です。ライブラリの一部になる可能性のあるコードを記述しようとしている場合は、このことを強く意識する必要があります。

一般的な、たとえば Web アプリやデスクトップ アプリのコードでは、それほど重要ではありません。ただし、フィールドにこれがないと、コードが読みにくくなり、プログラマーが混乱していることを示します。そのようなコードは、書き方が悪いという理由だけで安全である可能性は低いです。

于 2010-01-21T18:49:19.880 に答える
3

コードがより安全になるわけではなく、何よりもスレッドセーフのためです。変数が final とマークされている場合、オブジェクトの作成時に値を割り当てる必要があります。オブジェクトの作成後、その変数が別の値を参照するようにすることはできません。

この動作により、オブジェクトの状態について推論し、複数のスレッドが同時にアクセスしているときに特定の仮定を立てることができます。

于 2010-01-21T18:38:32.160 に答える
2

コードをより安全にすると言ったとき、誰かが何を意味するかはfinal、将来の開発者が変更することを意図していない値を変更したり、拡張するように設計されていないクラスから継承したりすることを防ぐことであると想像しますプロセスの結果)。認証とは (直接) 関係ありません。

于 2010-01-21T18:39:10.983 に答える
2

final は、アクセス修飾子がクラス宣言にあるのとほぼ同じように設計構成要素であると確信しています。これは、設計を表現および強制する方法です。

于 2010-01-21T19:19:22.640 に答える
1

「final」キーワードには、確かにセキュリティ上の意味があります。文字列が与えられ、その文字列が有効である場合にのみ何かを実行するサービスを持つ安全なシステムを設計していると想像してください。あなたは書くかもしれません:

public void doSomethingUseful(String argument) {
    checkValidity(argument);
    /* prepare to do something useful... preparation takes a bit of time! */
    reallyDoTheUsefulTask(argument);
}

String が final でない場合、巧妙な攻撃者が String をサブクラス化する可能性があります。それらの文字列は、ストック String クラスのように不変ではありません。実際、別のスレッドを生成し、checkValidity の後で実際に引数を使用する前に引数を変更することで、メソッドを攻撃しようとする可能性があります。次に、「便利なタスク」が突然完全に間違ったことを行い、セキュリティを損なう可能性があります。彼らはちょうどあなたのチェックをバイパスしました! ただし、java.lang.String は final であるため、String パラメーターを要求すると、実際には標準の不変 String であることが十分に保証されます。これは非常に大きな問題です。syscall による不適切なパラメーター処理に基づくカーネル モード攻撃のクラス全体がありました。

そうです、final にはいくつかのセキュリティ上の考慮事項があります。

于 2010-01-21T18:47:52.353 に答える
1

「確保する」というよりも、「変える」ことが重要です。最後のキーワードは、任意のメソッドを変更/修正/拡張する機能を単純に片付けます。

于 2010-01-21T18:37:40.483 に答える
1

Final は、パフォーマンス/メモリ管理も改善します。

于 2010-01-21T18:40:48.267 に答える