Bezpieczne programowanie w Javie – kontrola dostępu
©Wydawnictwo UR 2017
ISSN 2080-9069
ISSN 2450-9221 online
„Edukacja – Technika – Informatyka” nr 2/20/2017
www.eti.rzeszow.pl
DOI: 10.15584/eti.2017.2.42
JERZY KRAWIEC
Bezpieczne programowanie w Javie – kontrola dostępu
Security Programming in Java – Access Control
Doktor inżynier, Politechnika Warszawska, Wydział Inżynierii Produkcji, Instytut Organizacji
Systemów Produkcyjnych, Zakład Systemów Informatycznych, Polska
Streszczenie
Przedstawiono praktyczne aspekty bezpiecznego programowania w języku Java. Zbadano
znaczenie hermetyzacji jako kluczowego elementu kontroli dostępu do kodu źródłowego Javy.
Przeprowadzono badania reakcji maszyny wirtualnej Javy (JVM) w zależności od różnych wariantów zastosowanych specyfikatorów dostępu. Wyniki badań dowodzą, że konstrukcja kodu źródłowego odgrywa zasadniczą rolę w zapewnieniu bezpieczeństwa oprogramowania.
Słowa kluczowe: programowanie, bezpieczeństwo, kontrola dostępu, hermetyzacja
Abstract
The article discusses some aspects of safe Java programming. The importance of encapsulation as a key element of access control for Java source code has been examined. JVM has been
tested, depending on the variants of the access controllers used. Research shows that the design of
Java code plays a vital role in ensuring the software security.
Keywords: programming, security, access control, encapsulation
Wstęp
Programowanie to faza projektowania decydująca o sposobie budowy systemu informatycznego (Górny, Krawiec, 2016). Etap programowania powinien
przywiązywać szczególną uwagę do bezpieczeństwa budowanej aplikacji. Efektem projektowania systemu informatycznego może być struktura danych oraz
zestaw funkcji w strukturze programu (metodologia strukturalna). W przypadku
metodologii obiektowej rezultatem projektowania jest szczegółowy projekt obiektowy w postaci hierarchii klas z dziedziczeniem, zestaw atrybutów i metod charakteryzujących obiekty w ramach klas. Najczęstszymi błędami popełnianymi przez
programistów jest umożliwienie swobodnego dostępu do chronionych katalogów
przy wysokim prawdopodobieństwie zidentyfikowania tej podatności przez hakerów i jej wykorzystania np. poprzez kradzież danych (Krawiec, 2012). Język pro321
gramowania obiektowego powinien zapewnić mechanizmy, które umożliwią implementację modelu obiektowego. W Javie jednym z tych mechanizmów oprócz
dziedziczenia i polimorfizmu jest hermetyzacja (Schildt, 2014). Jest to mechanizm, który umożliwia połączenie kodu źródłowego i danych modyfikowanych
przez ten kod oraz tworzy zabezpieczenie przed dostępem zewnętrznym.
Hermetyzacja
Hermetyzacja jest traktowana jako powłoka ochronna systemu chroniąca
przed nieautoryzowanym dostępem z poziomu kodu spoza tej powłoki. Dostęp
do kodu i danych wewnątrz tej powłoki ochronnej jest determinowany przez
interfejsy obiektu. Podstawą hermetyzacji w Javie jest klasa, która decyduje
o strukturze i zachowaniu danych i kodu współdzielonych przez zbiór obiektów.
Szczegóły implementacji klasy powinny być chronione, gdyż ukrycie jej złożoności jest jej głównym zadaniem. Każda klasa i jej metody mogą być zadeklarowane jako publiczne, prywatne lub chronione. Z poziomu kodu źródłowego
danej klasy mogą być dostępne jedynie metody i dane prywatne. To oznacza, że
kod spoza klasy nie powinien mieć dostępu bezpośredniego do metod i zmiennej
prywatnej danej klasy (Downey, 2012).
Hermetyzacja, oprócz łączenia kodu i danych, dotyczy także bardzo ważnego elementu, jakim jest kontrola dostępu. Za pomocą hermetyzacji można definiować, który program może mieć dostęp do składowych klasy. Aby zapobiec
niewłaściwemu wykorzystaniu danych lub ich zmodyfikowaniu, należy je udostępniać za pomocą odpowiedniego interfejsu.
Modyfikatory dostępu
Z punktu widzenia bezpieczeństwa modyfikatory (specyfikatory) dostępu
w Javie pełnią istotną rolę. Zarządzają one prawami dostępu do klas i ich składowych. To oznacza, że dostęp do składowych klas (pól i metod) może być zdefiniowany jako: publiczny (public), prywatny (private), chroniony (protected)
lub pakietowy (package).
Dostęp publiczny oznacza, że dostęp nie jest niczym ograniczony i do tak
zadeklarowanej klasy mają go wszystkie inne klasy. To oznacza, że klasa i jej
składowe są dostępne do dowolnego innego kodu. W tym kontekście należy
zauważyć, że metoda main() jest zawsze poprzedzona specyfikatorem public,
gdyż jest wywoływana przez zewnętrzny kod, czyli system wykonawczy Javy
(JVM – Java Virtual Machine).
Klasy i składowe prywatne oznaczają, że dostęp do nich jest możliwy wyłącznie z wnętrza tej klasy. Możliwe jest odczytywanie i zapisywanie jedynie
przez metody tej klasy, natomiast dostęp z zewnątrz jest zabroniony (blokada
odczytu i zapisu).
Dostęp chroniony oznacza, że składowe klasy są dostępne tylko dla metod
tej klasy, klas potomnych oraz klas tego samego pakietu.
322
Klasy mogą być również pogrupowane w powiązane ze sobą zestawy zwane
bibliotekami lub pakietami.
Badania – mechanizm kontroli dostępu
Badania sposobu działania dostępu publicznego i prywatnego przeprowadzono na przykładzie programu do pobierania wartości zmiennych:
class Alfa {
int ab;
public int bc;
private int cd;
void ustaw_c(int i) {
cd = i;
}
int pobierz_cd() {
return cd;
}
}
class Beta {
public static void main(String jekr[]) {
Alfa obkt = new Alfa();
obkt.ab = 12;
obkt.bc = 28;
obkt.cd = 40; //Błąd!!!
obkt.ustaw_cd(40);
System.out.println("ab, bc, cd: "+ obkt.ab+ " " + obkt.bc+ "
" + obkt.pobierz_cd());
}
}
Składowa klasy Alfa (zmienna ab) nie używa żadnego specyfikatora (specyfikator domyślny), co w tym przypadku oznacza, że dostęp jest publiczny.
Zmienna bc ma specyfikator public, a zmienna cd używa specyfikatora private.
To oznacza, że klasa Beta nie ma możliwości bezpośredniego odwołania się do
zmiennej cd. Dlatego wykonanie linii kodu:
obkt.cd = 40;
skutkuje zgłoszeniem błędu dostępu w trakcie kompilacji. W związku z tym
najczęściej stosuje się takie rozwiązania, które wymuszają dostęp do danych
jedynie przez metody. Ponadto metody pomocnicze mogą być deklarowane jako
prywatne składowe klasy.
Wprowadzenie dostępu pakietowego (pakietów) chroni przez powstaniem
konfliktu nazw (Gosling, Joy, Steele, Bracha, Buckley, 2011). To oznacza, że
bez zastosowania tej techniki niemożliwe stałoby się jednoczesne skorzystanie
z dwóch klas w programie.
Brak specyfikatora dostępu oznacza, że składowe klasy są dostępne publicznie dla wszystkich innych klas, ale tylko z danego pakietu, czyli że składowe
klasy nie są dostępne dla kodu pochodzącego z innych pakietów.
323
Badania – praktyczny aspekt hermetyzacji
Badania praktycznego aspektu hermetyzacji przeprowadzono na przykładzie
stosu do przechowywania liczb całkowitych. Stos to implementacja struktury
danych pochodząca z klasy Stack. Stos przechowuje dane zgodnie z zasadą LIFO
(Last In First Out). Dane na stosie są umieszczane za pomocą metody push(),
a ich zdejmowanie w odwrotnej kolejności odbywa się za pomocą metody pop().
Klasa Delta1 definiuje stos liczb typu int przechowujący wartości do (...truncated)