Zapobiegaj wyświetlaniu przez użytkownika wcześniej odwiedzonej zabezpieczonej strony po wylogowaniu


99

Mam wymaganie, aby użytkownik końcowy nie mógł wrócić do strony z ograniczeniami po wylogowaniu / wylogowaniu się. Ale obecnie użytkownik końcowy może to zrobić za pomocą przycisku Wstecz przeglądarki, odwiedzając historię przeglądarki lub nawet ponownie wprowadzając adres URL w pasku adresu przeglądarki.

Zasadniczo chcę, aby użytkownik końcowy nie mógł w żaden sposób uzyskać dostępu do strony z ograniczeniami po wylogowaniu. Jak mogę to osiągnąć najlepiej? Czy mogę wyłączyć przycisk Wstecz w JavaScript?


7
Użyj wzorca post-request-get.

Odpowiedzi:


137

Możesz i nie powinieneś wyłączać przycisku wstecz lub historii przeglądarki. To źle wpływa na wrażenia użytkownika. Istnieją hacki JavaScript, ale nie są one niezawodne i nie będą działać, gdy klient ma wyłączony JS.

Twoim konkretnym problemem jest to, że żądana strona została załadowana z pamięci podręcznej przeglądarki, a nie prosto z serwera. Jest to zasadniczo nieszkodliwe, ale w rzeczywistości dezorientujące dla użytkownika końcowego, ponieważ błędnie uważa, że ​​tak naprawdę pochodzi z serwera.

Wystarczy poinstruować przeglądarkę, aby nie buforowała wszystkich zastrzeżonych stron JSP (a więc nie tylko samej strony wylogowania / akcji!). W ten sposób przeglądarka jest zmuszona zażądać strony z serwera zamiast z pamięci podręcznej, a zatem wszystkie testy logowania na serwerze zostaną wykonane. Możesz to zrobić za pomocą filtru, który ustawia niezbędne nagłówki odpowiedzi w doFilter()metodzie:

@WebFilter
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        response.setDateHeader("Expires", 0); // Proxies.

        chain.doFilter(req, res);
    }

    // ...
}

Na przykład mapuj to Filterna url-patterninteresujący Cię obiekt *.jsp.

@WebFilter("*.jsp")

Lub jeśli chcesz umieścić to ograniczenie tylko na zabezpieczonych stronach, powinieneś określić wzorzec adresu URL obejmujący wszystkie te zabezpieczone strony. Na przykład, gdy wszystkie znajdują się w folderze /app, musisz określić wzorzec adresu URL /app/*.

@WebFilter("/app/*")

Co więcej, możesz wykonać tę pracę w taki sam sposób, Filterjak sprawdzasz obecność zalogowanego użytkownika.

Nie zapomnij wyczyścić pamięci podręcznej przeglądarki przed testowaniem! ;)

Zobacz też:


2
Czasami to nie wystarcza, pamiętam taki problem. Przeglądarka po prostu pamięta ostatnią stronę. Ale mógł to być IE6, nie pamiętam :)
Bozho

3
@Bozho: Albo podałeś niekompletny zestaw nagłówków, albo przeglądarka wciąż ma stronę w pamięci podręcznej.
BalusC

1
@Chris: działa dla mnie z Firefoksem i wszystkimi innymi przeglądarkami. Twój problem jest spowodowany gdzie indziej. Być może zapomniałeś wyczyścić pamięć podręczną? Czy te nagłówki są ustawione na niewłaściwe odpowiedzi?
BalusC

@BalusC Utworzyłem oddzielną klasę Filter, aby zastąpić doFilter()metodę. Po naciśnięciu przycisku wylogowania następuje przekierowanie do serwletu, w którym unieważniam sesję. Nie jestem pewien, jak ta doFilter()metoda działa tutaj. Czy możesz mi powiedzieć, jak to wdrożyć? Jak w, właściwe kroki do naśladowania. Dzięki.
Anjan Baradwaj

Pracował dobrze dla mnie. Testowane po obu sendRedirect(...)i forward().
Hal50000

5

* .jsp we wzorcu adresu URL nie będzie działać, jeśli przekażesz stronę dalej. Spróbuj dołączyć także swój serwlet ... dzięki temu aplikacja będzie chroniona przed problemem z przyciskiem Wstecz.


2

Najprostszym sposobem na zrobienie tego bez wyłączania przycisku wstecz przeglądarki jest dodanie tego kodu do page_loadzdarzenia strony, do której użytkownik nie ma wracać po wylogowaniu:

if (!IsPostBack)
    {
        if (Session["userId"] == null)
        {
            Response.Redirect("Login.aspx");
        }
        else
        {
        Response.ClearHeaders();
        Response.ClearContent();
        Response.Clear();
        Session.Abandon();
        Session.Remove("\\w+");
        Response.AddHeader("Cache-Control", "no-cache, no-store, max-age = 0, must-revalidate");
        Response.AddHeader("Pragma", "no-cache");
        Response.AddHeader("Expires", "0");
        }
    }

6
Chociaż Twoja odpowiedź jest przydatna, prześlij ją, która odnosi się do wybranego języka programowania PO. Twoje rozwiązanie C # nie pomoże w projekcie Java EE OP.
Buhake Sindi

0

Możesz spróbować powiedzieć przeglądarce, aby nie buforowała strony głównej (używając odpowiednich nagłówków - Expires, Cache-Control, Pragma). Ale nie ma gwarancji, że zadziała. Co możesz zrobić, to wykonać wywołanie AJAX do serwera podczas ładowania strony, aby sprawdzić, czy użytkownik jest zalogowany, a jeśli nie - przekierować.


13
Ale jeśli zły umysł wyłączy JavaScript, to nie zadziała, a mimo to zobaczy stronę.
acme

0

Prawidłowym sposobem na to jest dodanie

Vary: Cookie

nagłówek na zabezpieczonych stronach. Gdy użytkownik się wyloguje, wyczyść jego sesyjny plik cookie. Następnie, gdy powrócą po wylogowaniu, pamięć podręczna przeglądarki zostanie pominięta. Ma to również tę zaletę, że nie pokonuje całkowicie buforowania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.