Jika anda sering membaca kod sumber, anda akan mendapati bahawa terdapat sekeping kod yang serupa dengan yang berikut di mana-mana dalam kod sumber 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>
Ini jelas merupakan kod semakan keselamatan, menyemak sama ada anda mempunyai akses keizinan laluan Cakera, mengapakah bahasa Java memerlukan kod semakan keselamatan sedemikian? Mari lihat kod sumber fungsi sambungan soket klien Ia perlu menyemak sama ada pengguna mempunyai kebenaran untuk menyambung ke alamat rangkaian tertentu
<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>
Mari lihat kod sumber bagi. soket pelayan sekali lagi. Ia akan menyemak kebenaran mendengar Port
<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>
Nampaknya semua panggilan kaedah yang berkaitan dengan operasi IO memerlukan pemeriksaan keselamatan. Nampaknya semakan kebenaran yang berkaitan dengan operasi IO boleh difahami, dan proses pengguna tidak boleh mengakses semua sumber IO sesuka hati. Tetapi pembolehubah persekitaran tidak dibenarkan dibaca sesuka hati, dan sekatannya bukan semua pembolehubah persekitaran, tetapi pembolehubah persekitaran tertentu Adakah pemeriksaan keselamatan ini terlalu banyak?
<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>
Ini kerana pengurus semakan keselamatan Java dan semakan kebenaran sistem pengendalian bukanlah konsep yang sama Java menulis bukan sahaja aplikasi bahagian pelayan, ia juga boleh dijalankan pada penyemak imbas sebagai klien. Applet), ia juga boleh dijalankan pada telefon mudah alih dalam bentuk aplikasi (J2ME), JVM akan menggunakan strategi keselamatan yang berbeza untuk platform yang berbeza. Biasanya, sekatan pada Applet adalah sangat ketat, dan Applet biasanya tidak dibenarkan untuk mengendalikan fail tempatan. Sebelum melaksanakan operasi IO tertentu, setelah semakan keselamatan Java lulus, sistem pengendalian masih akan melakukan semakan kebenaran.
Apabila kami biasanya menjalankan program java secara setempat, kami biasanya tidak membuka penyemak keselamatan secara lalai Kami perlu melaksanakan parameter jvm untuk membukanya
<code class="hljs shell">$ java -Djava.security.manager xxx<br>$ java -Djava.security.manager -DDjava.security.policy="${policypath}"<br></code>
Kerana sekatan keselamatan boleh. disesuaikan, ia juga Anda perlu menyediakan laluan fail dasar keselamatan khusus Laluan fail dasar lalai ialah JAVA_HOME/jre/lib/security/java.policy. Mari kita lihat apa yang ditulis dalam fail ini
<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>
berikan Jika parameter codeBase disediakan, peraturan kebenaran dikonfigurasikan untuk perpustakaan kelas tertentu Jika codeBase tidak ditentukan, peraturan dikonfigurasikan untuk semua perpustakaan kelas lain.
Jika semakan keselamatan gagal, pengecualian java.security.AccessControlException akan dilemparkan. Walaupun semakan keselamatan lulus, semakan kebenaran sistem pengendalian mungkin gagal, dalam hal ini jenis pengecualian lain akan dibuang.
Jika anda mengikut peraturan yang dikonfigurasikan di atas, JVM yang menggunakan dasar keselamatan lalai tidak akan dapat mengakses fail setempat kerana peraturan kebenaran menggunakan senarai putih. Jika anda perlu mengakses fail setempat, anda boleh menambah peraturan berikut
<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>
Parameter konfigurasi kebenaran betul-betul sepadan dengan parameter pembinanya
<code class="hljs java">public FilePermission(String path, String actions) {<br> super(path);<br> init(getMask(actions));<br>}<br></code>
Peraturan keselamatan lalai Java dibahagikan kepada beberapa modul Besar, setiap modul mempunyai parameter konfigurasi sendiri
di mana AllPermission bermaksud membuka semua kebenaran. Terdapat juga tetamu yang tidak diundang, HibernatePermission, yang bukan modul kebenaran terbina dalam Ia disesuaikan oleh rangka kerja Hibernate, yang bermaksud bahawa peraturan keselamatan menyokong sambungan tersuai. Untuk melanjutkan adalah mudah, hanya tulis subkelas Kebenaran dan laksanakan empat kaedah abstraknya.
<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>
Apabila JVM bermula, ia akan memuatkan peraturan kebenaran yang ditakrifkan dalam profil ke dalam kumpulan kebenaran Program pengguna menggunakan kumpulan kebenaran dalam kaedah API tertentu untuk menentukan sama ada ia mengandungi kebenaran untuk panggil API ini Akhirnya, ia akan Ia dilaksanakan dengan memanggil kaedah tersirat setiap objek kebenaran dalam kumpulan kebenaran untuk menentukan sama ada ia mempunyai kebenaran yang ditentukan.
<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>
Mendayakan semakan keselamatan akan mengurangkan kecekapan pelaksanaan program Jika terdapat terlalu banyak peraturan kebenaran yang ditakrifkan dalam profil, kecekapan semakan akan menjadi sangat perlahan apabila menggunakannya pemeriksaan keselamatan dan gunakannya dengan berhati-hati.
Terdapat banyak pusat pemeriksaan keselamatan dalam kotak pasir Berikut ialah beberapa senario biasa
Operasi fail
Operasi Soket
Atas ialah kandungan terperinci Apakah mekanisme kotak pasir keselamatan untuk aplikasi Java?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!