Apakah metode privat benar-benar aman?

92

Di Java, privatepengubah akses dianggap aman karena tidak terlihat di luar kelas. Kemudian dunia luar juga tidak tahu tentang metode itu.

Tapi saya pikir refleksi Java dapat digunakan untuk melanggar aturan ini. Pertimbangkan kasus berikut:

public class ProtectedPrivacy{

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

}  

Sekarang dari kelas lain saya akan mendapatkan Info:

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());
   }
} 

Saat ini saya hanya berpikir metode private masih aman karena untuk melakukan hal-hal seperti diatas kita harus mengetahui nama metode. Tetapi jika kelas yang berisi metode privat yang ditulis oleh orang lain, kami tidak memiliki visibilitasnya.

Tetapi poin saya menjadi tidak valid karena baris kode di bawah ini.

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

Sekarang ini method[]berisi semua hal yang perlu dilakukan di atas. Pertanyaan saya adalah, adakah cara untuk menghindari hal semacam ini dilakukan dengan menggunakan refleksi Java?

Saya mengutip beberapa poin dari Dokumentasi Java untuk memperjelas pertanyaan saya.

Tips Memilih Tingkat Akses:

Jika pemrogram lain menggunakan kelas Anda, Anda ingin memastikan bahwa kesalahan dari penyalahgunaan tidak dapat terjadi. Tingkat akses dapat membantu Anda melakukan ini. Gunakan tingkat akses paling ketat yang masuk akal untuk anggota tertentu. Gunakan pribadi kecuali Anda punya alasan kuat untuk tidak melakukannya.

Ruchira Gayan Ranaweera
sumber
1
Menggunakan obfuscator dapat membantu, karena getDeclaredMethodsakan mengembalikan nama yang terlihat seperti sampah.
dasblinkenlight
213
Pribadi, publik yang dilindungi, dll. Bukan untuk keamanan, itu untuk menghindari orang yang bermaksud baik dari membuat kesalahan. Jangan menggunakannya sebagai tindakan keamanan
Richard Tingle
20
Kode Java tetap dapat didekompilasi. Seorang 'penyerang' bisa saja mendownload decompiler Java dan membaca kode Anda, atau mengubah 'private' menjadi 'public'.
11684
7
Untuk menguraikan apa yang dikomentari @RichardTingle (+1 btw). Ada perbedaan besar dan penting antara keamanan dan keselamatan. Dimana yang terakhir adalah masalah yang diatasi dengan pengubah akses; untuk tidak merusak barang secara tidak sengaja
pengguna
3
Semua ini cukup jelas bagi programmer di mana pengubah akses tidak ada, seperti di Python. Dalam bahasa ini privat / publik hanya dibedakan dengan konvensi dalam nama (dalam python apa pun yang dimulai dengan satu garis bawah harus dianggap privat). Hal ini memperjelas bahwa menandai sesuatu sebagai "pribadi" tidak menambah keamanan apa pun, tetapi ini hanya cara sederhana untuk mengatakan apa yang harus digunakan orang - orang dari API Anda. Saya ragu bahwa pemeriksaan kompiler untuk hal-hal ini sangat membantu karena sangat mudah mengikuti konvensi tanpa bantuan "eksternal".
Bakuriu

Jawaban:

95

Itu tergantung pada apa yang Anda maksud dengan "aman". Jika Anda menjalankan dengan manajer keamanan yang memungkinkan hal semacam ini, maka ya, Anda dapat melakukan semua jenis hal buruk dengan refleksi. Tapi kemudian dalam lingkungan semacam itu perpustakaan mungkin hanya bisa dimodifikasi untuk membuat metode menjadi publik.

Kontrol akses secara efektif "memberi nasihat" dalam lingkungan seperti itu - Anda secara efektif mempercayai kode untuk bermain dengan baik. Jika Anda tidak mempercayai kode yang Anda jalankan, Anda harus menggunakan pengelola keamanan yang lebih ketat.

Jon Skeet
sumber
3
Tangential, saya tahu, tetapi dapatkah Anda menjelaskan sedikit tentang manajer yang lebih ketat dalam pengertian ini?
Abu
12
@Gray: Sebuah instance dari SecurityManager yang pada check*dasarnya memberikan pengecualian pada panggilan yang relevan .
Jon Skeet
40

Pengubah akses tidak ada hubungannya dengan keamanan. Sebenarnya Anda dapat dan harus melihat pengubah akses sebagai kebalikan dari keamanan - ini bukan untuk melindungi data atau algoritme Anda, ini untuk melindungi orang dari persyaratan untuk mengetahui tentang data dan algoritme Anda. Inilah sebabnya mengapa pengubah default adalah paket - jika mereka mengerjakan paket, mereka mungkin perlu mengetahuinya.

Seiring dengan pengetahuan tentang data dan metode kode Anda, muncullah tanggung jawab untuk mengetahui kapan dan bagaimana menggunakannya. Anda tidak menempatkan privat pada metode inIt Anda untuk mencegah seseorang mengetahuinya, Anda melakukannya karena (a) mereka tidak akan tahu bahwa Anda hanya memanggilnya setelah foo dan hanya jika bar = 3.1415 dan (b) karena tidak ada gunanya mereka mengetahuinya.

Modifers akses dapat diringkas dalam kalimat sederhana "TMI, dude, aku jadi tidak perlu tahu bahwa".

jmoreno
sumber
3
Jawaban yang bagus, tapi saya memang perlu google untuk mengetahui bahwa TMI berarti Terlalu Banyak Informasi. Saya rasa saya perlu menghabiskan lebih banyak waktu di lembah :-)
mikelong
7

Dengan mengatakan 'aman', Anda melindungi Anda atau pengembang lain, yang menggunakan API Anda untuk tidak merusak objek dengan memanggil metode pribadi Anda. Tetapi jika Anda atau mereka benar-benar perlu memanggil metode ini, mereka dapat melakukannya dengan Reflection.

Arsen Alexanyan
sumber
6

Pertanyaannya adalah dari siapa Anda mencoba menyelamatkannya . Menurut pendapat saya, klien kode Anda yang seperti itu adalah orang yang merugi di sini.

Setiap bagian kode (ditulis oleh Anda atau orang lain) yang mencoba mengakses anggota privatekelas di atas pada dasarnya menggali kuburannya sendiri. privateanggota tidak membuat bagian dari API publik dan dapat berubah tanpa pemberitahuan. Jika klien kebetulan mengonsumsi salah satu anggota privat dengan cara yang diberikan di atas, klien akan rusak jika meningkatkan ke versi API yang lebih baru di mana anggota privat dimodifikasi.

hthserhs
sumber
5

Dengan fasilitas, ada tanggung jawab. Ada hal-hal yang tidak dapat Anda lakukan, & hal-hal yang dapat Anda lakukan tetapi tidak boleh Anda lakukan.

Pengubah pribadi disediakan / digunakan sebagai / dengan cara yang paling terbatas. Anggota yang tidak boleh terlihat di luar kelas harus didefinisikan sebagai pribadi. Tapi ini bisa dipatahkan dengan Refleksi seperti yang kita lihat. Tetapi ini tidak berarti bahwa Anda tidak boleh menggunakan pribadi - atau mereka tidak aman. Ini tentang Anda harus menggunakan hal-hal dengan bijaksana atau dengan cara yang konstruktif (seperti refleksi).

Raúl
sumber
5

Dengan asumsi Anda mempercayai programmer klien API Anda, cara lain untuk melihat adalah seberapa 'aman' bagi mereka untuk menggunakan fungsi-fungsi khusus tersebut.

Fungsi Anda yang tersedia untuk umum harus menyediakan antarmuka yang jelas, terdokumentasi dengan baik, dan jarang berubah ke dalam kode Anda. Fungsi pribadi Anda dapat dianggap sebagai detail implementasi dan dapat berubah seiring waktu, jadi tidak aman untuk digunakan secara langsung.

Jika programmer klien berusaha keras untuk menghindari abstraksi ini, mereka dengan cara menyatakan bahwa mereka tahu apa yang mereka lakukan. Lebih penting lagi, mereka memahami bahwa itu tidak didukung dan mungkin berhenti berfungsi dengan versi kode Anda yang akan datang.

robbie_c
sumber
5

privatebukan untuk keamanan, ini untuk menjaga kode tetap bersih dan untuk mencegah kesalahan. Ini memungkinkan pengguna untuk memodularisasi kode (dan bagaimana itu dikembangkan) tanpa harus khawatir tentang semua detail dari modul lain

Setelah Anda merilis kode, orang-orang dapat mengetahui cara kerjanya. Tidak ada cara untuk "menyembunyikan" logika jika pada akhirnya Anda ingin kode dijalankan di komputer. Bahkan mengompilasi ke biner hanyalah tingkat kebingungan.

Jadi, tidak mungkin Anda dapat menyiapkan API untuk melakukan hal-hal khusus yang Anda tidak ingin orang lain panggil. Dalam kasus API web, Anda dapat meletakkan metode yang ingin Anda kontrol di sisi server.

Manishearth
sumber