Apakah Refleksi merugikan karena variabel pribadi tidak dapat dibatasi?

14

The privatepengubah digunakan untuk membatasi akses luar kelas, tetapi menggunakan refleksi kelas lain dapat mengakses metode pribadi dan bidang. Jadi saya bertanya-tanya bagaimana kita dapat membatasi aksesibilitas jika itu merupakan bagian dari persyaratan.

pengguna245930
sumber
2
Kode kepercayaan rendah tidak dapat menggunakan refleksi pribadi (setidaknya tidak pada majelis lain, saya lupa detailnya). Kode kepercayaan penuh hanya dapat menggunakan pointer untuk melewati batasan apa pun dalam proses.
CodesInChaos
55
Pengubah akses pribadi terutama ada untuk memberi tahu pemrogram "tidak menggunakan ini dari luar kelas, dan jika Anda benar-benar melakukannya, jangan mengeluh jika versi berikutnya memecah kode Anda" bukan sebagai fitur keamanan yang ditegakkan secara ketat.
CodesInChaos
4
Pengguna juga dapat menambal kode Anda untuk melakukan apa pun yang mereka inginkan. Dengan pengecualian parsial untuk DRM (yang tidak cukup kuat untuk memberikan perlindungan abadi), siapa pun yang memiliki akses ke aplikasi Anda (binari atau kode sumber) dapat melakukan apa saja dengan itu.
Brian
6
Bukankah ini pertanyaan khusus bahasa? Refleksi beroperasi secara berbeda dalam berbagai bahasa. Saya bertanya-tanya apakah pertanyaan ini harus memiliki tag untuk Java atau sesuatu yang lain.
Wayne Conrad

Jawaban:

54

Tujuan pengubah akses adalah untuk memberi tahu pengembang menulis kode tentang apa yang dimaksud dengan antarmuka publik kelas. Mereka tidak dengan cara apa pun mengukur keamanan dan mereka tidak benar-benar menyembunyikan atau mengamankan informasi apa pun.

JacquesB
sumber
33
Ini tidak benar secara universal. Mengutip Eric Lippert , "Pengubah akses di CLR adalah fitur keamanan. Aturan untuk akses sepenuhnya terkait dengan sistem keamanan dan jenis keselamatan." Di C #, Reflection hanya tersedia untuk kode yang berjalan di bawah kepercayaan penuh. Ini tidak (dan tidak bisa) berlaku untuk pengguna jahat dari sistem yang menjalankan kode. Namun, itu berlaku untuk plug-in berbahaya.
Brian
5
@ Brian Dimana masalah yang Brian sebutkan adalah relevan ketika suatu sistem memungkinkan kode pihak ketiga untuk berjalan tanpa sepenuhnya mempercayainya. Contohnya termasuk kotak pasir peramban (mis. Applet yang sangat dibenci), mesin aplikasi google dan Azure . Akan sangat bodoh bagi Azure untuk mengizinkan kode yang tidak dipercaya untuk menjelajahi detail pustaka inti platform.
JimmyJames
3
@Brian Itu tidak 100% benar - ada beberapa operasi refleksi yang dapat Anda lakukan dalam kode yang dipercaya sebagian; itu hanya tidak memungkinkan Anda untuk melakukan hal-hal seperti mengakses bidang pribadi.
Luaan
1
@Brian Hingga seseorang menemukan kerentanan atau rekayasa sosial yang memungkinkan mereka melewati batasan. Tidak ada gunanya mencoba menggunakannya dengan cara itu. Itu bukan tujuan utama mereka.
jpmc26
31

Mengutip Herb Sutter tentang hak akses kelas :

"Masalahnya di sini adalah melindungi terhadap Murphy vs. melindungi terhadap Machiavelli ... yaitu, melindungi dari penyalahgunaan yang tidak disengaja (yang bahasa ini sangat baik) vs melindungi dari penyalahgunaan yang disengaja (yang secara efektif tidak mungkin). Pada akhirnya, jika seorang programmer sangat ingin menumbangkan sistem, dia akan menemukan cara "

Nemanja Trifunovic
sumber
2
Ada saat - saat di mana Anda perlu sandbox kode yang tidak dipercaya, tetapi itu adalah tugas yang menakutkan. Melindungi dari kesalahan (Murphy) adalah kasus yang jauh lebih umum.
Paul Draper
#define private public(mengabaikan bahwa itu sebenarnya Perilaku Tidak Terdefinisi) dan voila saya memiliki akses penuh dari luar ke bagian terbatas dari kelas Anda.
bolov
Melindungi dari pelecehan yang disengaja mungkin secara teori tidak mungkin tetapi secara efektif dimungkinkan, dengan membuat pelecehan cukup sulit sehingga jarang terjadi. Penting untuk menjelaskan hal itu. Kalau tidak, perangkat lunak tidak dapat digunakan sama sekali dalam situasi seperti perangkat medis yang kritis.
MarkJ
@MarkJ. Komentar Herb Sutter adalah tentang pelecehan yang disengaja oleh pengembang yang menulis kelas di tempat pertama dan mungkin rekan satu timnya. Saya tidak berpikir ada cara untuk mencegah penyalahgunaan semacam itu oleh fitur bahasa.
Nemanja Trifunovic
@bolov akrobat itu tergantung pada bahasa saya pikir. Sementara C / C ++ preprocessor mungkin akan membiarkan Anda lolos begitu saja, apa pun tanpa mereka mungkin akan memberikan kesalahan "tidak dapat menggunakan kata-kata yang dicadangkan dalam kesalahan #define".
Dan is Fiddling oleh Firelight
10

Tidak, ini sebenarnya keuntungan penting. Hanya karena beberapa pengembang tidak menganggap bahwa siapa pun akan memerlukan akses ke keadaan internal tidak berarti bahwa tidak ada kasus penggunaan yang sah yang akan muncul. Dalam kasus ini, menggunakan Refleksi untuk melakukan operasi pada suatu objek dapat menjadi pilihan terakhir. Saya harus menggunakan teknik ini lebih dari sekali.

Mason Wheeler
sumber
1
Dengan kata lain, ini adalah cara untuk menghindari kemungkinan API yang rusak - apakah karena persyaratan yang tidak lengkap atau implementasi yang tidak lengkap.
Pasang kembali Monica
4

Anda membatasi aksesibilitas lebih banyak lagi dengan naik satu tingkat lagi: lingkungan eksekusi.

Tidak semua bahasa memiliki konsep ini, tetapi setidaknya dengan Java Anda dapat menggunakan manajer keamanan yang melarang membuat bidang pribadi dapat diakses. Anda bisa menginstal manajer keamanan secara manual saat runtime, atau menambahkan kebijakan keamanan dalam file jar yang kemudian disegel untuk mencegah modifikasi.

Informasi lebih lanjut tentang melakukan ini di Jawa: Keamanan Refleksi

Komunitas
sumber
3

Refleksi apa yang Anda bicarakan?

Dalam banyak sistem refleksi, menghindari enkapsulasi adalah kemampuan eksplisit yang perlu diperoleh kode Anda, dan tidak memilikinya secara default.

Jika Anda khawatir tentang enkapsulasi, solusi sederhananya adalah dengan tidak menggunakan sistem refleksi yang tidak melestarikannya.

Jörg W Mittag
sumber
3

Dalam Python, tidak ada pengubah akses. Konvensi tersebut adalah awalan dengan menggarisbawahi metode dan variabel yang tidak diharapkan untuk diakses dari luar kelas. Apakah ini secara teknis mencegah Anda mengakses bidang tersebut dari kelas pihak ketiga? Tidak semuanya; tetapi jika Anda melakukannya, Anda sendirian dan mengambil risiko melanggar sesuatu, tanpa bisa menyalahkan kelas lain.

Di C #, pengubah akses ada, tetapi mereka hanya sebuah konvensi — yang dipaksakan oleh kompiler, tetapi masih sebuah konvensi. Ini berarti bahwa secara teknis, seseorang masih dapat mengakses dan mengubah variabel pribadi, baik melalui Refleksi atau dengan merusak memori secara langsung (seperti yang dilakukan pelatih game ). Konsekuensinya persis sama: jika variabel kelas Anda diubah melalui Refleksi dari kelas lain, atau melalui memori yang diubah oleh aplikasi lain, dan itu merusak sesuatu di kelas Anda, itu bukan kesalahan Anda.

Perhatikan bahwa ini, jelas, menciptakan masalah keamanan di mana pihak ketiga dapat mengakses data Anda ; sesuatu yang mengarah ke varian string dan struktur data serupa yang dienkripsi . Tetapi melindungi kode Anda dari penggunaan semacam itu lebih terkait dengan OS dan pembatasan akses tingkat kode , dan tidak ada hubungannya dengan Refleksi semata.

Arseni Mourzenko
sumber
2
Perhatikan bahwa dalam C #, hanya kode yang sepenuhnya tepercaya yang dapat mencerminkan anggota pribadi. Menulis secara langsung untuk memproses memori masih berfungsi, tetapi lebih sulit daripada dalam kode asli.
Luaan