Özel yöntemler gerçekten güvenli midir?


92

Java'da privateerişim değiştirici, sınıfın dışında görünmediği için güvenli kabul edilir. O zaman dış dünya da bu yöntemi bilmiyor.

Ancak Java yansımasının bu kuralı çiğnemek için kullanılabileceğini düşündüm. Aşağıdaki durumu düşünün:

public class ProtectedPrivacy{

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

}  

Şimdi başka bir dersten Bilgi alacağım:

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

Şu anda hala özel yöntemin güvenli olduğunu düşündüm, çünkü yukarıdaki gibi bir şey yapmak için yöntemin adını bilmemiz gerekir. Ama eğer bir başkası tarafından yazılmış özel yöntem içeren bir sınıf varsa, bunların görünürlüğümüz yok.

Ama benim açımdan aşağıdaki kod satırından beri geçersiz hale geldi.

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

Şimdi bu method[]yukarıda yapılması gereken her şeyi içerir. Sorum şu, Java yansımasını kullanarak bu tür şeylerden kaçınmanın bir yolu var mı?

Soruma açıklık getirmek için Java Belgelerinden bir noktadan alıntı yapıyorum .

Erişim Düzeyi Seçmeye İlişkin İpuçları:

Diğer programcılar sınıfınızı kullanırsa, yanlış kullanımdan kaynaklanan hataların olmamasını sağlamak istersiniz. Erişim düzeyleri bunu yapmanıza yardımcı olabilir. Belirli bir üye için anlamlı olan en kısıtlayıcı erişim düzeyini kullanın. Yapmamak için iyi bir nedeniniz yoksa özel kullanın.


1
Bir obfuscator kullanmak getDeclaredMethodsişe yarayabilir, çünkü çöp gibi görünen isimler döndürür.
Sergey Kalinichenko

213
Özel, korumalı kamu vb. Güvenlik için değil, iyi niyetli insanların hata yapmasını önlemek içindir. Bunu bir güvenlik önlemi olarak kullanmayın
Richard Tingle

20
Java kodu zaten derlenemez. Bir 'saldırgan' bir Java kod çözücüsünü indirip kodunuzu okuyabilir veya 'özel'i' genel 'olarak değiştirebilir.
11684

7
@RichardTingle'ın yorumladığı şeyi detaylandırmak için (+1 btw). Güvenlik ve emniyet arasında büyük ve önemli bir fark vardır. İkincisi, erişim değiştiricilerle hafifletilen sorun olduğunda; kazayla bir
kullanıcı

3
Python'da olduğu gibi erişim değiştiricilerin bulunmadığı programcılar için tüm bunlar oldukça açıktır. Bu dillerde özel / genel, isimlerdeki bir kongre ile ayırt edilir (python'da tek bir alt çizgiyle başlayan her şey özel olarak kabul edilmelidir). Bu oldukça "özel" olarak bir şeyler işaretleme anlamına temizlemek yapar değil herhangi bir güvenlik eklemek, ama insanlar neyi söylemenin sadece basit bir yolu olmalı senin API kullanın. "Dışarıdan" yardım olmadan konvansiyonu takip etmek çok kolay olduğundan, bu şeyler için bir derleyici kontrolüne sahip olmanın her şeye yardımcı olduğuna dair şüphelerim var.
Bakuriu

Yanıtlar:


95

"Güvenli" ile ne demek istediğine bağlı. Bu tür şeylere izin veren bir güvenlik yöneticisiyle çalışıyorsanız, o zaman evet, düşünerek her türlü kötü şeyi yapabilirsiniz. Ancak bu tür bir ortamda, kütüphane muhtemelen yöntemi yine de herkese açık hale getirmek için değiştirilebilir.

Böyle bir ortamda erişim kontrolü etkili bir şekilde "tavsiye niteliğindedir" - koda güzel bir şekilde oynaması için etkili bir şekilde güveniyorsunuz. Eğer varsa yok yayınladığınız kodu güven, daha kısıtlayıcı bir güvenlik yöneticisi kullanmalıdır.


3
Teğetsel, biliyorum, ama bu anlamda daha kısıtlayıcı bir yöneticinin ne olacağı konusunda biraz ayrıntı verebilir misiniz?
Grey

12
@Gray: Temel olarak ilgili çağrılara istisnalar atan bir SecurityManager örneği check*.
Jon Skeet

40

Erişim değiştiricilerin güvenlikle ilgisi yoktur. Aslında, erişim değiştiricilere güvenliğin tersi olarak bakabilirsiniz ve bakmalısınız - verilerinizi veya algoritmalarınızı korumak değil, insanları verileriniz ve algoritmalarınız hakkında bilgi edinme gereksiniminden korumaktır. Varsayılan değiştiricinin paket olmasının nedeni budur - paket üzerinde çalışıyorlarsa muhtemelen zaten bilmeleri gerekir.

Verilerin bilgisi ve kodunuzun yöntemlerinin yanı sıra, onu ne zaman ve nasıl kullanacağınızı bilme sorumluluğu gelir. Birinin bunu öğrenmesini engellemek için inIt yönteminize özel koymazsınız, bunu yaparsınız çünkü (a) bunu yalnızca foo'dan sonra ve yalnızca bar = 3.1415 ise ve (b) çünkü bunu bilmelerinin onlara bir faydası yok.

Erişim Modifers basit ifadesinde özetlenebilir "TMI, ahbap, ben bu yüzden olduğunu bilmek gerek yoktu".


3
Harika cevap, ancak TMI'nin Çok Fazla Bilgi anlamına geldiğini öğrenmek için Google'a ihtiyacım vardı. Sanırım vadide daha fazla zaman geçirmem gerekiyor :-)
mikelong

7

'Güvenli' diyerek, özel yönteminizi çağırarak nesneye zarar vermemek için API'nizi kullanan sizi veya diğer geliştiricileri koruyorsunuz. Ancak siz veya onlar gerçekten bu yöntemi çağırmaları gerekiyorsa, bunu Yansıma ile yapabilirler.


6

Soru, onu kimden kurtarmaya çalıştığın . Kanımca, kodunuzun böyle bir müşterisi burada kaybolan kişidir.

privateYukarıdaki sınıfın bir üyesine erişmeye çalışan (sizin veya başkaları tarafından yazılan) herhangi bir kod parçası , aslında kendi mezarını kazıyor. privateüyeler genel API'nin bir parçasını oluşturmaz ve önceden haber verilmeksizin değiştirilebilir. Bir müşteri bu tür özel üyelerden birini yukarıda belirtilen şekilde tüketirse, özel üyenin değiştirildiği API'nin daha yeni bir sürümüne yükseltilirse, işlem bozulacaktır.


5

Tesisle birlikte sorumluluk gelir. Orada şey var olan edemez yapmak, & İşlerin olabilir yapmak ama olmamalı yapmak.

Özel değiştirici, en kısıtlı şekilde / olarak sağlanır / kullanılır. Sınıfın dışında görünmemesi gereken üyeler özel olarak tanımlanacaktır. Ancak bu, gördüğümüz gibi Yansıma ile kırılabilir. Ancak bu, özel kullanmamanız gerektiği veya güvensiz oldukları anlamına gelmez. Her şeyi mantıklı veya yapıcı bir şekilde (yansıtma gibi) kullanmanızla ilgilidir.


5

API'nizin istemci programcısına güvendiğinizi varsayarsak, başka bir bakma yolu da bu belirli işlevleri kullanmanın onlar için ne kadar 'güvenli' olduğudur.

Herkese açık işlevleriniz, kodunuza açık, iyi belgelenmiş, nadiren değişen bir arayüz sağlamalıdır. Özel işlevleriniz bir uygulama ayrıntısı olarak düşünülebilir ve zamanla değişebilir, bu nedenle doğrudan kullanılması güvenli değildir.

Bir istemci programcısı bu soyutlamaları atlatmak için yolundan çekilirse, bir şekilde ne yaptıklarını bildiğini beyan etmiş olur. Daha da önemlisi, desteklenmediğini anlarlar ve kodunuzun gelecekteki sürümleriyle çalışmayı durdurabilirler.


5

privategüvenlik için değil, kodu temiz tutmak ve hataları önlemek içindir. Kullanıcıların , diğer modüllerin tüm detayları hakkında endişelenmek zorunda kalmadan kodu (ve nasıl geliştirildiğini) modülerleştirmesine olanak tanır.

Kodunuzu yayınladığınızda, insanlar nasıl çalıştığını anlayabilir. Sonunda kodun bir bilgisayarda çalışmasını istiyorsanız mantığı "gizlemenin" bir yolu yoktur. İkiliye derlemek bile bir gizleme düzeyidir.

Bu nedenle, API'nizi başkalarının arayamasını istemediğiniz özel şeyler yapacak şekilde ayarlamanın bir yolu yoktur. Bir web API söz konusu olduğunda, kontrol etmek istediğiniz yöntemleri sunucu tarafına koyabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.