Mechanizm filtrów umożliwia odrzucenie żądań do aplikacji. Jest to mechanizm szczególnie przydatny kiedy chcemy zabezpieczyć aplikacje przed połączeniami:
- z niechcianych adresów stron;
- atakami DDos;
- serwerami proxy;
- adresów znajdujących się na liście phishing-u;
- niepożądanymi użytkownikami;
Zasada działania
Domyślnie aplikacja pozbawiona filtrów przetwarza wszystkie żądania. W przypadku kiedy filtr jest obecny wszystkie żądania przechodzą najpierw przez filtr, a dopiero po przejściu przez niego wykonywana jest właściwa obsługa żądania użytkownika.
Takie rozwiązanie pociąga za sobą konsekwencje. Definitywną korzyścią jest odrzucenie niechcianych żądań jeszcze przed przetworzeniem jej przez aplikacje – oszczędność zasobów sprzętowych. Jednak w przypadku kiedy filtr jest obecny dochodzi to trzeba ją traktować jako dodatkową warstwę, wówczas powoduje to wydłużenie czasu odpowiedzi dla użytkownika.
Interfejs Filter
Interfejs javax.servlet.Filter posiada trzy metody do przeciążenia
- public void init(FilterConfig filterConfig) throws ServletException;
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
- public void destroy();
Pierwsza z nich init odpowiada za internalizacje Filtru. Kontener serwletu wywołuje metodę init po utworzeniu filtra.
Druga metoda doFilter powinna zawierać sprawdzenie czy przechwycone żądanie spełnia założone warunki
Ostatnia metoda destroy odpowiada za wyczyszczenie stanu np. z wykorzystywanych zasobów czy też uchwytów.
Implementacja
Dla testu utworzona zostanie prosta metoda webowa:
@RestController public class TestApi { @GetMapping("/test") public static String example() { return "hello!"; } }
Teraz zostanie dodana klasa rozszerzająca interfejs javax.servlet.Filter
@Component public class SecurityFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (request.getRemoteAddr() == "https://bykowski.pl") { chain.doFilter(request, response); } else { response.getWriter().write("Tego Pana nie obsługujemy"); } } @Override public void destroy() { } }
Obowiązkowo zostały nadpisane trzy w/w metody.
W przypadku testu, zawołania metody REST – pokazuje się komunikat:
Dzieje się tak dlatego ponieważ w pierwszej kolejności żądanie przechwytuje Filter. Wewnątrz metody doFilter został sprawdzony warunek na to czy host z jakiego żądanie pochodzi to „https://bykowski.pl”. Ponieważ nie jest to prawdą to wyświetlił się komunikat zawarty w sekcji else.
W przypadku, kiedy warunek zostałby spełniony wykonałby się fragment kodu:
chain.doFilter(request, response);
Odpowiedzialny za przekazanie obsługi żądania dalej – w tym przypadku do metody example() z klasy TestApi.
W kolejnej części opisany zostanie sposób integrowania aplikacji Spring Boot z zewnętrznym API.