ソース コードをよく読むと、Java ソース コードに次のようなコードがあることがわかります。
<code class="hljs java">class File {<br> // 判断一个磁盘文件是否存在<br> public boolean exists() {<br> SecurityManager security = System.getSecurityManager();<br> if (security != null) {<br> security.checkRead(path);<br> }<br> ...<br> }<br>}<br></code>
これは明らかにセキュリティ チェック コードです。ディスク パスへのアクセス権限があるかどうかに関係なく、なぜ Java 言語にそのようなセキュリティ チェック コードが必要なのでしょうか?クライアント ソケットの connect 関数のソース コードを見てみましょう。この関数は、ユーザーが特定のネットワーク アドレスに接続する権限を持っているかどうかを確認する必要があります。
<code class="hljs cs">class Socket {<br> public void connect(SocketAddress endpoint, int timeout) {<br> ...<br> SecurityManager security = System.getSecurityManager();<br> if (security != null) {<br> if (epoint.isUnresolved())<br> security.checkConnect(epoint.getHostName(), port);<br> else<br> security.checkConnect(addr.getHostAddress(), port);<br> }<br> }<br> ...<br> }<br>}<br></code>
のソース コードを見てみましょう。サーバーソケット。ポートのリスニング許可をチェックします
<code class="hljs cs">class ServerSocket {<br> public void bind(SocketAddress endpoint, int backlog) {<br> ...<br> SecurityManager security = System.getSecurityManager();<br> if (security != null)<br> security.checkListen(epoint.getPort());<br> ...<br> }<br>}<br></code>
IO操作に関連するすべてのメソッド呼び出しにはセキュリティチェックが必要なようです。 IO 操作に関連する権限チェックは理解できるようで、ユーザー プロセスはすべての IO リソースに自由にアクセスできません。しかし、環境変数であっても自由に読み込むことはできず、制限されるのはすべての環境変数ではなく特定の環境変数です このセキュリティチェックはちょっとやりすぎでしょうか?
<code class="hljs cs">class System {<br> public static String getenv(String name) {<br> SecurityManager sm = getSecurityManager();<br> if (sm != null) {<br> sm.checkPermission(new RuntimePermission("getenv."+name));<br> }<br> return ProcessEnvironment.getenv(name);<br> }<br>}<br></code>
これは、Java のセキュリティ チェック マネージャーとオペレーティング システムの権限チェックは同じ概念ではないためです。Java はサーバー側のアプリケーションを作成するだけでなく、ブラウザ上でクライアントとして実行することもできます。(アプレット)、アプリ (J2ME) の形式で携帯電話上で実行することもできます。JVM はプラットフォームごとに異なるセキュリティ戦略を使用します。通常、アプレットに対する制限は非常に厳しく、アプレットはローカル ファイルを操作することは一般的に許可されていません。特定の IO 操作を実行する前に、Java のセキュリティ チェックに合格すると、オペレーティング システムは引き続き権限チェックを実行します。
通常、Java プログラムをローカルで実行する場合、デフォルトではセキュリティ チェッカーは開きません。開くには、jvm パラメータを実行する必要があります。
<code class="hljs shell">$ java -Djava.security.manager xxx<br>$ java -Djava.security.manager -DDjava.security.policy="${policypath}"<br></code>
セキュリティ制限はカスタマイズできるため、また、特定のセキュリティ ポリシー ファイル パスを指定する必要があります。デフォルトのポリシー ファイル パスは JAVA_HOME/jre/lib/security/java.policy です。このファイルに何が書かれているか見てみましょう
<code class="hljs dart">// 内置扩展库授权规则<br>// 表示 JAVA_HOME/jre/lib/ext/ 目录下的类库可以全权访问任意资源<br>// 包含 javax.swing.*, javax.xml.*, javax.crypto.* 等等<br>grant codeBase "file:${{java.ext.dirs}}/*" {<br> permission java.security.AllPermission;<br>};<br><br>// 其它类库授权规则<br>grant {<br> // 允许线程调用自己的 stop 方法自杀<br> permission java.lang.RuntimePermission "stopThread";<br> // 允许程序监听 localhost 的随机可用端口,不允许随意订制端口<br> permission java.net.SocketPermission "localhost:0", "listen";<br> // 限制获取系统属性,下面一系列的配置都是只允许读部分内置属性<br> permission java.util.PropertyPermission "java.version", "read";<br> permission java.util.PropertyPermission "java.vendor", "read";<br> permission java.util.PropertyPermission "java.vendor.url", "read";<br> permission java.util.PropertyPermission "java.class.version", "read";<br> permission java.util.PropertyPermission "os.name", "read";<br> permission java.util.PropertyPermission "os.version", "read";<br> permission java.util.PropertyPermission "os.arch", "read";<br> permission java.util.PropertyPermission "file.separator", "read";<br> permission java.util.PropertyPermission "path.separator", "read";<br> permission java.util.PropertyPermission "line.separator", "read";<br> permission java.util.PropertyPermission "java.specification.version", "read";<br> permission java.util.PropertyPermission "java.specification.vendor", "read";<br> permission java.util.PropertyPermission "java.specification.name", "read";<br> permission java.util.PropertyPermission "java.vm.specification.version", "read";<br> permission java.util.PropertyPermission "java.vm.specification.vendor", "read";<br> permission java.util.PropertyPermission "java.vm.specification.name", "read";<br> permission java.util.PropertyPermission "java.vm.version", "read";<br> permission java.util.PropertyPermission "java.vm.vendor", "read";<br> permission java.util.PropertyPermission "java.vm.name", "read";<br>};<br></code>
grant codeBase パラメーターが指定されている場合、アクセス許可ルールは特定のクラス ライブラリに対して構成されます。codeBase が指定されていない場合、ルールは他のすべてのクラス ライブラリに対して構成されます。
セキュリティ チェックが失敗した場合、java.security.AccessControlException 例外がスローされます。セキュリティ チェックに合格した場合でも、オペレーティング システムのアクセス許可チェックが失敗する場合があり、その場合は他の種類の例外がスローされます。
上で構成したルールに従う場合、認可ルールではホワイトリストが使用されるため、デフォルトのセキュリティ ポリシーを使用する JVM はローカル ファイルにアクセスできなくなります。ローカル ファイルにアクセスする必要がある場合は、次のルールを追加できます
<code class="hljs lua">permission java.io.FilePermission "/etc/passwd", "read";<br>permission java.io.FilePermission "/etc/shadow", "read,write";<br>permission java.io.FilePermission "/xyz", "read,write,delete";<br>// 允许读所有文件<br>permission java.io.FilePermission "*", "read";<br></code>
Permission の構成パラメータはコンストラクタ パラメータに正確に対応します
<code class="hljs java">public FilePermission(String path, String actions) {<br> super(path);<br> init(getMask(actions));<br>}<br></code>
Java のデフォルトのセキュリティ ルールは次のとおりです。いくつかの大きなモジュールに分割されており、各モジュールには独自の構成パラメータ
があり、AllPermission はすべてのアクセス許可を開くことを意味します。また、組み込みのアクセス許可モジュールではなく、招待されていないゲスト HibernatePermission もあり、Hibernate フレームワークによってカスタマイズされており、セキュリティ ルールがカスタム拡張機能をサポートしています。拡張は簡単で、Permission サブクラスを作成し、その 4 つの抽象メソッドを実装するだけです。
<code class="hljs java">abstract class Permission {<br> // 权限名称,对于文件来说就是文件名,对于套接字来说就是套接字地址<br> // 它的意义是子类可定制的<br> private String name;<br> // 当前权限对象是否隐含了 other 权限<br> // 比如 AllPermission 的这个方法总是返回 true<br> public abstract boolean implies(Permission other);<br> // equals 和 hashcode 用于权限比较<br> public abstract boolean equals(Object obj);<br> public abstract int hashCode();<br> // 权限选项 read,write,xxx<br> public abstract String getActions();<br>}<br><br>class CustomPermission extends Permission {<br> private String actions;<br> CustomPermission(string name, string actions) {<br> super(name)<br> this.actions = actions;<br> }<br> ...<br>}<br></code>
JVM が起動すると、プロファイルで定義された権限ルールが権限プールにロードされます。ユーザー プログラムは、特定の API メソッドで権限プールを使用して、次の権限が含まれているかどうかを判断します。この API は、最終的には、アクセス許可プール内の各アクセス許可オブジェクトの implies メソッドを呼び出して、指定されたアクセス許可があるかどうかを判断することによって実装されます。
<code class="hljs cs">class CustomAPI {<br> public void someMethod() {<br> SecurityManager sec = System.getSecurityManager();<br> if(sec != null) {<br> sec.CheckPermission(new CustomPermission("xname", "xactions"));<br> }<br> ...<br> }<br>}<br></code>
セキュリティチェックを有効にすると、プログラムの実行効率が低下します。プロファイルに定義された権限ルールが多すぎると、チェック効率が非常に遅くなります。使用する場合は、安全性を確認し、慎重に使用してください。
サンドボックスには多くのセキュリティ チェックポイントがあります。一般的なシナリオをいくつか示します
ファイル操作
ソケット操作
スレッドとスレッド グループ
クラス ローダー コントロール
リフレクション コントロール
スレッドスタック情報取得
以上がJava アプリケーションのセキュリティ サンドボックス メカニズムとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。