JavaRush /Blog Java /Random-PL /JAAS – Wprowadzenie do technologii (część 2)
Viacheslav
Poziom 3

JAAS – Wprowadzenie do technologii (część 2)

Opublikowano w grupie Random-PL
Ciąg dalszy pierwszej części artykułu o JAAS. Zastanówmy się, czy w JAAS można używać samych adnotacji i jakie problemy napotkamy. W tej części dowiemy się, które narzędzia Servlet API pozwalają nam uczynić kod bardziej uniwersalnym. I podsumujmy to, co przeczytaliśmy.
JAAS – Wprowadzenie do technologii (Część 2) – 1

Kontynuacja

W pierwszej części przeglądu technologii JAAS (patrz „ JAAS – Wprowadzenie do technologii (część 1) ”) przyjrzeliśmy się głównemu przypadkowi użycia JAAS i Servlet API. Widzieliśmy, że kontener serwletów Tomcat zarządzał bezpieczeństwem naszej aplikacji internetowej przy użyciu architektury JAAS. Mając wiedzę na temat „metody autoryzacji” i „Security Realm”, kontener Tomcat sam zapewnił nam niezbędną implementację mechanizmu uwierzytelniania i sam zapewnił nam CallbackHandler, wykorzystaliśmy to wszystko w naszym module logowania. Należy jedynie pamiętać, że przeglądarka zapisuje dane dotyczące loginu i hasła przesyłane w ramach uwierzytelniania BASIC. Dlatego przy każdym nowym skanowaniu za pomocą przeglądarki Chrome możesz nacisnąć Ctrl+Shift+N, aby otworzyć nowe okno do pracy w trybie incognito.
JAAS – Wprowadzenie do technologii (część 2) – 2

Adnotacje

Konfiguracja za pomocą XML już dawno wyszła z mody. Dlatego ważne jest, aby powiedzieć, że począwszy od wersji Servlet API 3.0, mamy możliwość ustawiania ustawień serwletu za pomocą adnotacji, bez korzystania z pliku deskryptora wdrażania web.xml. Zobaczmy jak zmieni się zarządzanie bezpieczeństwem, jeśli zastosujemy adnotacje. I czy możliwe jest wdrożenie opisanych powyżej podejść za pomocą adnotacji? Specyfikacja Servlet API i jej sekcja „ Adnotacje i możliwość podłączania ” ponownie pomogą nam zrozumieć adnotacje . Ta sekcja mówi, że deklarację serwletu web.xmlmożna zastąpić adnotacją @WebServlet. W związku z tym nasz serwlet będzie wyglądał następująco:
@WebServlet(name="app", urlPatterns = "/secret")
public class App extends HttpServlet {
Następnie spójrzmy na rozdział „ 13.3 Bezpieczeństwo programowe ”. Mówi, że możemy również zadeklarować ograniczenie bezpieczeństwa poprzez adnotacje:
@WebServlet(name="app", urlPatterns = "/secret")
@ServletSecurity(httpMethodConstraints = {
        @HttpMethodConstraint(value = "GET", rolesAllowed = "admin")
})
public class App extends HttpServlet {
Teraz web.xmlw naszym pozostał już tylko jeden blok - login-config. Problem w tym, że tak się składa, że ​​łatwo i prosto go nie da się wymienić. Ze względu na ścisły związek pomiędzy ustawieniami zabezpieczeń aplikacji internetowych i ustawieniami zabezpieczeń serwera WWW, nie ma prostego i uniwersalnego sposobu, aby to zrobić, nawet programowo. Jest to jeden z problemów związanych z uwierzytelnianiem za pomocą JAAS i Servlet API. Mówiąc o bloku login-configwarto zrozumieć, że jest to deklaratywny opis Mechanizmów Uwierzytelniających, tj. mechanizmy uwierzytelniania. Nadal nie ma prostego, uniwersalnego sposobu na jego zastąpienie, bo... przetwarzanie web.xmlodbywa się głęboko w kontenerach serwletów. Na przykład w Tomcat możesz sprawdzić plik źródłowy ContextConfig.java . Dlatego nawet w przypadku kontenera serwletów Tomcat istnieje kilka opcji i wszystkie są różne. Przykładowo, jeśli korzystamy z kontenera serwletów Embedded Tomcat (czyli podnosimy serwer WWW z kodu), to o takich opcjach można przeczytać tutaj: „ Embedded Tomcat z podstawowym uwierzytelnianiem poprzez kod ”. Ponadto ogólny przykład uruchomienia Embedde Tomcat można zobaczyć w przewodniku po platformie Heroku PaaS: „ Tworzenie aplikacji internetowej Java przy użyciu Embedded Tomcat ”. Jeśli Tomcat nie jest używany w trybie osadzonym, w przypadku Tomcat możesz zastosować powszechnie stosowane podejście - detektory zdarzeń. W Tomcat jest to „ Komponent odbiornika cyklu życia ”. Jednocześnie ważne jest, aby zrozumieć, że kontenery serwletów (w naszym przypadku Tomcat) mogą mieć własne moduły ładujące klasy i nie będzie możliwe po prostu pobranie i użycie twoich klas. W przypadku Tomcata musisz zrozumieć „Instrukcję obsługi modułu ładującego klasy ”. W innym kontenerze serwletów o nazwie Undertow można to osiągnąć za pomocą „ Rozszerzeń serwletów ”. Jak widać, niektóre zapewniły bardziej elastyczne mechanizmy, inne nie. Jak widać, nie ma jednej opcji. Wszystkie są bardzo różne. Czy można w jakiś sposób zrobić coś uniwersalnego, korzystając wyłącznie z Servlet API i JAAS? W Internecie można znaleźć propozycję wykorzystania Servlet Filter do przeprowadzenia uwierzytelnienia bez blokady login-config. Rozważmy w końcu tę opcję. To pozwoli nam powtórzyć działanie JAAS.
JAAS – Wprowadzenie do technologii (część 2) – 3

Filtr autoryzacji

Naszym celem jest więc całkowite pozbycie się web.xmlpliku. Jeśli się go pozbędziemy, to niestety nie będziemy już mogli korzystać z ograniczenia bezpieczeństwa, ponieważ ich przetwarzanie może nastąpić znacznie wcześniej niż zastosowane zostaną filtry serwletów. To opłata, jaką trzeba zapłacić za „uniwersalność” stosowania filtrów. Te. będziemy musieli usunąć adnotację @ServletSecurity, a wszystkie kontrole, które poprzednio opisaliśmy w ograniczeniu bezpieczeństwa, będą musiały zostać przeprowadzone programowo. Jak widać, ta opcja również narzuca nam wiele przykrych ograniczeń. Przede wszystkim usuńmy adnotację @ServletSecurityz zasobu i blok login-configz pliku web.xml. Teraz sami będziemy musieli wdrożyć uwierzytelnianie podstawowe. Teraz dodajmy nasz filtr:
@WebFilter("/*")
public class JaasFilter implements javax.servlet.Filter {
Póki co wydaje się to proste. Napiszmy metodę inicjalizacji:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
	String jaas_conf = filterConfig.getServletContext().getRealPath("/WEB-INF/jaas.config");
	System.getProperties().setProperty("java.security.auth.login.config",jaas_conf);
}
Jak widać, jesteśmy teraz zmuszeni użyć podstawowych narzędzi JAAS do wyszukiwania pliku konfiguracyjnego jaas. Ma to dużą wadę - jeśli jest kilka aplikacji, to jedna aplikacja może złamać uwierzytelnienie drugiej. Sposób ogólnego ustawienia pliku konfiguracyjnego Jaas opisano szczegółowo w dokumentacji JAAS: „ Dodatek A: Ustawienia JAAS w pliku właściwości zabezpieczeń java.security ”. Następnie opiszemy samą metodę filtrowania. Zacznijmy od otrzymania żądania HTTP:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	HttpServletRequest req = (HttpServletRequest) request;
	// Если в реквесте уже есть Principal - ничего не делаем
	if (req.getUserPrincipal() != null ) {
		chain.doFilter(request, response);
	}
Tutaj wszystko jest proste. Jeśli podmiot zabezpieczeń jest dostępny, uwierzytelnianie zakończyło się pomyślnie. Następnie należy opisać działanie filtra, gdy użytkownik nie przeszedł uwierzytelnienia, czyli tzw. nie został jeszcze rozpoznany. Wcześniej opisaliśmy podstawową metodę uwierzytelniania BASIC. Ponieważ Ponieważ teraz sami piszemy filtr, będziemy musieli dowiedzieć się, jak faktycznie działa uwierzytelnianie w języku BASIC. Możesz użyć „ Dokumenty internetowe MDN: autoryzacja HTTP ”. A także „ Jak działa uwierzytelnianie HTTP? ” Z opisu działania uwierzytelniania podstawowego jasno wynika, że ​​jeśli serwer chce przeprowadzić uwierzytelnienie BASIC, a użytkownik nie podał danych, to serwer wysyła specjalny nagłówek „WWW-Authenticate” i kod błędu 401. Utwórzmy wewnętrzna metoda tego:
private void requestNewAuthInResponse(ServletResponse response) throws IOException {
	HttpServletResponse resp = (HttpServletResponse) response;
	String value = "Basic realm=\"JaasLogin\"";
	resp.setHeader("WWW-Authenticate", value);
	resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
Teraz skorzystajmy z tej metody i dodajmy doFilterdo niej następujący blok kodu:
// Получаем security Header. А если его нет - запрашиваем
String secHeader = req.getHeader("authorization");
if (secHeader == null) {
	requestNewAuthInResponse(response);
}
Dodajmy teraz gałąź dla if, która zostanie wykonana, gdy nagłówek zostanie już przesłany:
// Проверяем аутентификацию
else {
	String authorization = secHeader.replace("Basic ", "");
	Base64.Decoder decoder = java.util.Base64.getDecoder();
	authorization = new String(decoder.decode(authorization));
	String[] loginData = authorization.split(":");
	try {
		if (loginData.length == 2) {
			req.login(loginData[0], loginData[1]);
			chain.doFilter(request, response);
		} else {
			requestNewAuthInResponse(response);
		}
	} catch (ServletException e) {
		requestNewAuthInResponse(response);
	}
}
Do tego kodu możesz dodać autoryzację, np.: req.isUserInRole("admin") Zatem dokonaliśmy u Ciebie uwierzytelnienia za pomocą filtra. Z jednej strony jest dużo kodu i ręcznego przetwarzania. Z drugiej strony istnieje wszechstronność i niezależność serwera.
JAAS – Wprowadzenie do technologii (część 2) – 4

Wniosek

Dotarliśmy do końca tej recenzji. Mam nadzieję, że teraz stanie się trochę jaśniejsze, czym jest JAAS, podmiotem i zleceniodawcami. Słowa Security Realm i Login Config nie będą już powodować pytań. Ponadto wiemy już, jak jednocześnie używać JAAS i Servlet API. Ponadto dowiedzieliśmy się o wąskich gardłach, w których adnotacje w Servlet API nas nie uratują. Oczywiście to nie wszystko. Na przykład uwierzytelnianie w Javie może nie być tylko PODSTAWOWE. O innych typach możesz przeczytać w specyfikacji Servlet API w sekcji „ 13.6 Uwierzytelnianie ”. W Internecie trudno znaleźć szczegółowe informacje na temat JAAS. Ale mogę polecić ten materiał: Mam nadzieję, że informacje zawarte w tej recenzji będą przydatne i zrozumiałe. #Wiaczesław
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION