プライベートメソッドは本当に安全ですか?


92

Javaでは、privateアクセス修飾子はクラスの外からは見えないため、安全であると見なされます。それから、外の世界もその方法について知りません。

しかし、Javaリフレクションはこのルールを破るために使用できると思いました。次のケースを検討してください。

public class ProtectedPrivacy{

  private String getInfo(){
     return "confidential"; 
  }

}  

次に、別のクラスから情報を取得します。

public class BreakPrivacy{

   public static void main(String[] args) throws Exception {
       ProtectedPrivacy protectedPrivacy = new ProtectedPrivacy();
       Method method = protectedPrivacy.getClass().getDeclaredMethod("getInfo", null);
       method.setAccessible(true);
       Object result = method.invoke(protectedPrivacy);
       System.out.println(result.toString());
   }
} 

上記のようなことをするためにはメソッド名を知らなければならないので、現時点では私はまだプライベートメソッドが安全だと思っていました。しかし、他の誰かが作成したプライベートメソッドを含むクラスの場合、それらの可視性はありません。

しかし、コード行の下なので、私のポイントは無効になります。

Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();

これにmethod[]は、上記のことを行うために必要なすべてのものが含まれています。私の質問は、Javaリフレクションを使用してこのようなことを回避する方法はありますか?

私の質問を明確にするために、Javaドキュメンテーションからいくつかのポイントを引用します。

アクセスレベルの選択に関するヒント:

他のプログラマがクラスを使用する場合、誤用によるエラーが発生しないようにする必要があります。アクセスレベルは、これを行うのに役立ちます。特定のメンバーにとって意味のある最も制限されたアクセスレベルを使用します。正当な理由がない限り、プライベートを使用してください。


1
難読化ツールを使用すると、getDeclaredMethodsガベージのように見える名前が返されるため、役立つ場合があります。
dasblinkenlight 2013年

213
私的、保護された公共などはセキュリティのためではなく、人々が過ちを犯すことを意味しないようにすることです。セキュリティ対策として使用しないでください
Richard Tingle 2013年

20
とにかくJavaコードは逆コンパイル可能です。「攻撃者」は、Javaデコンパイラをダウンロードしてコードを読み取るか、「プライベート」を「パブリック」に変更するだけです。
11684 2013年

7
@RichardTingleがコメントした内容を詳しく説明する(+1 btw)。セキュリティと安全性の間には、重要で重要な違いがあります。後者は、アクセス修飾子で緩和される問題です。誤って
ユーザーの

3
これは、Pythonのようにアクセス修飾子が存在しないプログラマーには非常に明確です。これらの言語では、private / publicは名前の規則によって単純に区別されます(pythonでは、単一の下線で始まるものはすべてプライベートと見なされます)。これにより、何かを「プライベート」としてマークしてもセキュリティが追加されないことは明らかですが、これは、人々 APIをどのように使用すべきかを示す簡単な方法にすぎませ。「外部」の助けなしに規約に従うのはとても簡単なので、コンパイラーがこのことをチェックすることはまったく役立つのではないかと疑っています。
Bakuriu 2013年

回答:


95

それはあなたが「安全」とはどういう意味かによる。このようなことを許可するセキュリティマネージャーを使用している場合は、そうです。そうすれば、リフレクションを使用してあらゆる種類の厄介なことを実行できます。しかし、そのような環境では、おそらくライブラリを変更して、とにかくメソッドをパブリックにすることができます。

そのような環境では、アクセス制御は事実上「助言」であり、コードが適切に機能することを事実上信頼しています。実行しているコードが信頼できない場合は、より制限の厳しいセキュリティマネージャを使用する必要があります。


3
接線、わかりますが、この意味でより制限的な管理者が何であるかについて少しだけ詳しく説明できますか?
グレー

12
@Gray:基本的に、関連する呼び出しで例外をスローするSecurityManagerのインスタンスcheck*
Jon Skeet 2013年

40

アクセス修飾子はセキュリティとは何の関係もありません。実際には、アクセス修飾子をセキュリティの逆と見なすことができます。これは、データやアルゴリズムを保護するためではなく、データやアルゴリズムについて知る必要から人々を保護するためです。これが、デフォルトの修飾子がパッケージである理由です。彼らがパッケージで作業している場合、おそらくすでに知っておく必要があります。

データとコードのメソッドの知識に加えて、いつどのように使用するかを知る責任が伴います。誰かがそれを知らないようにするためにinItメソッドにプライベートを設定しないでください。なぜなら、(a)fooの後で、bar = 3.1415および(b)の場合にのみそれが呼び出されることを彼らは知らないためです。それは彼らがそれについて知るのは良くないからです。

アクセス修飾子は、「TMI、おい、私はそれを知る必要がなかった」という簡単なフレーズで要約できます。


3
すばらしい答えですが、TMIが多すぎる情報であることを知るためにググる必要がありました。谷でもっと時間を過ごす必要があると思います:-)
mikelong 2013年

7

「安全」と言うことで、あなたは、あなた自身または他の開発者を保護します。開発者は、APIを使用して、プライベートメソッドを呼び出すことによってオブジェクトに害を与えません。しかし、あなたまたは彼らが本当にこのメソッドを呼び出す必要がある場合、彼らはReflectionでそれを行うことができます。


6

問題は、誰から保存しようとしているのかということです。私の意見では、あなたのコードのそのようなクライアントはここで途方に暮れるものです。

private上記のクラスのメンバーにアクセスしようとするコード(あなたや他の人が書いた)は、本質的に自分の墓を掘っています。privateメンバーはパブリック APIの一部ではなく、予告なしに変更される場合があります。クライアントが上記の方法でそのようなプライベートメンバーの1つを使用した場合、プライベートメンバーが変更されたAPIの新しいバージョンにアップグレードすると、クライアントは壊れます。


5

施設には責任があります。そこの事はあなたがいていることができないん、&あなたは物事ができませんが、あなたはいけませんありません。

プライベート修飾子は、最も制限された方法で提供/使用されます。クラスの外部に表示されるべきではないメンバーは、プライベートとして定義されます。しかし、これはリフレクションで解決できます。しかし、これはプライベートを使用すべきではないという意味ではありません-またはそれらは安全ではありません。それはあなたが物事を賢明にまたは建設的な方法で(反射のように)使用することについてです。


5

APIのクライアントプログラマーを信頼していると仮定すると、別の見方は、特定の関数を使用することが「安全」であることです。

公開されている関数は、明確で十分に文書化され、ほとんど変更されないインターフェイスをコードに提供する必要があります。プライベート関数は実装の詳細と見なすことができ、時間とともに変化する可能性があるため、直接使用するのは安全ではありません。

クライアントプログラマーがこれらの抽象化を回避しようとする場合、彼らは、自分が何をしているのかを知っていることを宣言しています。さらに重要なことに、彼らはそれがサポートされていないことを理解しており、あなたのコードの将来のバージョンでは機能しなくなるかもしれません。


5

privateセキュリティのためではなく、コードをクリーンに保ち、ミスを防ぐためです。他のモジュールの詳細すべてを気にすることなく、コード(およびコードの開発方法)をモジュール化できます。

コードをリリースすると、人々はそれがどのように機能するかを理解できます。最終的にコードをコンピューターで実行したい場合、ロジックを「隠す」方法はありません。バイナリにコンパイルすることも、難読化のレベルです。

したがって、他の人に呼び出されたくない特別なことを実行するようにAPIを設定する方法はありません。Web APIの場合、制御したいメソッドをサーバー側に置くことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.