W Javie private
modyfikator dostępu uważa się za bezpieczny, ponieważ nie jest widoczny poza klasą. Wtedy świat zewnętrzny również nie wie o tej metodzie.
Ale pomyślałem, że odbicie w Javie może użyć do złamania tej reguły. Rozważ następujący przypadek:
public class ProtectedPrivacy{
private String getInfo(){
return "confidential";
}
}
Teraz z innej klasy otrzymam informacje:
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());
}
}
W tej chwili uważałem, że nadal prywatna metoda jest bezpieczna, ponieważ aby zrobić coś takiego jak powyżej, musimy znać nazwę metody. Ale jeśli klasa zawiera metody prywatne napisane przez kogoś innego, nie mamy ich widoczności.
Ale mój punkt stał się nieważny, ponieważ poniższy wiersz kodu.
Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();
Teraz method[]
zawiera wszystkie rzeczy, które należy zrobić powyżej. Moje pytanie brzmi: czy istnieje sposób na uniknięcie tego rodzaju działań przy użyciu odbicia w języku Java?
Cytuję pewien punkt z dokumentacji Java, aby wyjaśnić moje pytanie.
Wskazówki dotyczące wyboru poziomu dostępu:
Jeśli inni programiści używają Twojej klasy, chcesz mieć pewność, że błędy wynikające z niewłaściwego użycia nie wystąpią. Poziomy dostępu mogą ci w tym pomóc. Użyj najbardziej restrykcyjnego poziomu dostępu, który ma sens dla konkretnego członka. Użyj prywatnego, chyba że masz dobry powód, aby tego nie robić.
źródło
getDeclaredMethods
zwróci nazwy, które wyglądają jak śmieci.Odpowiedzi:
Zależy to od tego, co masz na myśli mówiąc „bezpieczny”. Jeśli pracujesz z menedżerem ds. Bezpieczeństwa, który na to pozwala, to tak, możesz robić różne nieprzyjemne rzeczy z refleksją. Ale w takim środowisku bibliotekę można prawdopodobnie po prostu zmodyfikować, aby mimo to upublicznić metodę.
Kontrola dostępu jest faktycznie „doradcza” w takim środowisku - skutecznie ufasz, że kod będzie dobrze działał. Jeśli nie ufasz uruchomionemu kodowi, powinieneś użyć bardziej restrykcyjnego menedżera bezpieczeństwa.
źródło
check*
zasadzie generuje wyjątki w odpowiednich wywołaniach.Modyfikatory dostępu nie mają nic wspólnego z bezpieczeństwem. W rzeczywistości możesz i powinieneś traktować modyfikatory dostępu jako odwrotność bezpieczeństwa - nie ma to na celu ochrony Twoich danych ani algorytmów, ale ma chronić ludzi przed wymogiem posiadania wiedzy o Twoich danych i algorytmach. Dlatego domyślnym modyfikatorem jest pakiet - jeśli pracują nad pakietem, prawdopodobnie już muszą wiedzieć.
Wraz ze znajomością danych i metodami Twojego kodu przychodzi odpowiedzialność za to, aby wiedzieć, kiedy i jak go używać. Nie ustawiasz prywatnego na swojej metodzie inIt, aby ktoś nie dowiedział się o tym, robisz to, ponieważ (a) nie będą wiedzieć, że wywołasz to tylko po foo i tylko jeśli bar = 3.1415 i (b) ponieważ wiedza o tym nie pomoże im.
Modyfikatory dostępu można podsumować prostym zwrotem „TMI, stary, nie musiałem tego wiedzieć”.
źródło
Mówiąc „bezpieczny”, chronisz siebie lub innych programistów, którzy używają twojego API, aby nie uszkodzić obiektu, wywołując twoją prywatną metodę. Ale jeśli Ty lub oni naprawdę musicie wywołać tę metodę, mogą to zrobić za pomocą Reflection.
źródło
Pytanie brzmi, od kogo próbujesz go uratować . Moim zdaniem taki klient twojego kodu jest tutaj stracony.
Każdy fragment kodu (napisany przez Ciebie lub inne osoby), który próbuje uzyskać dostęp do
private
członka powyższej klasy, jest w zasadzie kopaniem własnego grobu.private
członkowie nie stanowią części publicznego interfejsu API i mogą ulec zmianie bez powiadomienia. Jeśli zdarzy się, że klient zużyje jednego z takich prywatnych członków w sposób podany powyżej, zepsuje się, jeśli zaktualizuje do nowszej wersji API, w którym prywatny członek został zmodyfikowany.źródło
Łatwość wiąże się z odpowiedzialnością. Są rzeczy, których nie możesz zrobić i rzeczy, które możesz zrobić, ale nie powinieneś .
Prywatny modyfikator jest dostarczany / używany jako / w najbardziej ograniczony sposób. Elementy członkowskie, które nie powinny być widoczne poza klasą, należy zdefiniować jako prywatne. Ale, jak widzimy, można to złamać za pomocą Refleksji. Ale to nie znaczy, że nie powinieneś używać prywatnych - lub są one niebezpieczne. Chodzi o to, abyś używał rzeczy rozsądnie lub w konstruktywny sposób (jak refleksja).
źródło
Zakładając, że ufasz programistom klienta twojego API, innym spojrzeniem jest to, jak „bezpieczne” jest korzystanie z tych konkretnych funkcji.
Twoje publicznie dostępne funkcje powinny zapewniać przejrzysty, dobrze udokumentowany, rzadko zmieniający się interfejs w kodzie. Twoje prywatne funkcje mogą być traktowane jako szczegół implementacji i mogą się zmieniać w czasie, więc nie są bezpieczne w użyciu bezpośrednio.
Jeśli programista kliencki robi wszystko, co w jego mocy, aby ominąć te abstrakcje, w pewien sposób deklaruje, że wie, co robi. Co ważniejsze, rozumieją, że nie jest on obsługiwany i może przestać działać z przyszłymi wersjami Twojego kodu.
źródło
private
nie służy bezpieczeństwu, lecz zachowaniu czystości kodu i zapobieganiu błędom. Pozwala użytkownikom na modularyzację kodu (i sposobu jego tworzenia) bez martwienia się o wszystkie szczegóły innych modułówPo wydaniu kodu ludzie mogą dowiedzieć się, jak to działa. Nie ma sposobu, aby „ukryć” logikę, jeśli ostatecznie chcesz, aby kod działał na komputerze. Nawet kompilacja do formatu binarnego to tylko poziom zaciemnienia.
Nie ma więc możliwości skonfigurowania interfejsu API do robienia specjalnych rzeczy, których nie chcesz, aby inni mogli wywoływać. W przypadku internetowego interfejsu API metody, nad którymi chcesz mieć kontrolę, można umieścić po stronie serwera.
źródło