Ngăn người dùng xem trang bảo mật đã truy cập trước đó sau khi đăng xuất


99

Tôi có yêu cầu rằng người dùng cuối không thể quay lại trang bị hạn chế sau khi đăng xuất / đăng xuất. Nhưng hiện tại người dùng cuối có thể làm điều đó bằng nút quay lại trình duyệt, truy cập lịch sử trình duyệt hoặc thậm chí bằng cách nhập lại URL vào thanh địa chỉ của trình duyệt.

Về cơ bản, tôi muốn rằng người dùng cuối sẽ không thể truy cập trang bị hạn chế theo bất kỳ cách nào sau khi đăng xuất. Làm thế nào tôi có thể đạt được điều này tốt nhất? Tôi có thể tắt nút quay lại bằng JavaScript không?


7
Sử dụng mẫu Post-request-get.Google nó.

Câu trả lời:


137

Bạn có thể và không nên tắt nút quay lại hoặc lịch sử của trình duyệt. Điều đó không tốt cho trải nghiệm người dùng. Có các bản hack JavaScript, nhưng chúng không đáng tin cậy và cũng sẽ không hoạt động khi máy khách đã tắt JS.

Vấn đề cụ thể của bạn là trang được yêu cầu được tải từ bộ nhớ cache của trình duyệt thay vì trực tiếp từ máy chủ. Điều này về cơ bản là vô hại, nhưng thực sự gây nhầm lẫn cho người dùng cuối, bởi vì họ nghĩ sai rằng nó thực sự đến từ máy chủ.

Bạn chỉ cần hướng dẫn trình duyệt không lưu vào bộ nhớ cache tất cả các trang JSP bị hạn chế (và do đó không chỉ trang đăng xuất / hành động!). Bằng cách này, trình duyệt buộc phải yêu cầu trang từ máy chủ thay vì từ bộ đệm và do đó tất cả các kiểm tra đăng nhập trên máy chủ sẽ được thực hiện. Bạn có thể thực hiện việc này bằng Bộ lọc đặt các tiêu đề phản hồi cần thiết trong doFilter()phương thức:

@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);
    }

    // ...
}

Ví dụ: ánh xạ điều này Filtertrên một url-patternmối quan tâm *.jsp.

@WebFilter("*.jsp")

Hoặc nếu bạn chỉ muốn đặt hạn chế này trên các trang được bảo mật, thì bạn nên chỉ định mẫu URL bao gồm tất cả các trang được bảo mật đó. Ví dụ: khi tất cả chúng đều nằm trong thư mục /app, thì bạn cần chỉ định mẫu URL của /app/*.

@WebFilter("/app/*")

Thậm chí, bạn có thể thực hiện công việc này giống Filternhư khi bạn đang kiểm tra sự hiện diện của người dùng đã đăng nhập.

Đừng quên xóa bộ nhớ cache của trình duyệt trước khi thử nghiệm! ;)

Xem thêm:


2
Đôi khi điều này là không đủ, tôi nhớ có một vấn đề như vậy. Trình duyệt chỉ nhớ trang cuối cùng. Nhưng nó có thể là IE6, tôi không thể nhớ lại :)
Bozho

3
@Bozho: Bạn đã cung cấp bộ tiêu đề chưa hoàn chỉnh hoặc trình duyệt vẫn có trang trong bộ nhớ cache.
BalusC

1
@Chris: phù hợp với tôi với Firefox và tất cả các trình duyệt khác. Vấn đề của bạn là do nơi khác. Có lẽ bạn đã quên xóa một số bộ nhớ cache? Hoặc những tiêu đề đó được đặt trên các phản hồi sai?
BalusC

@BalusC Tôi đã tạo một lớp Bộ lọc riêng để ghi đè doFilter()phương thức. Khi tôi nhấn nút đăng xuất, nó được chuyển hướng đến một servlet nơi tôi làm mất hiệu lực của phiên. Tôi không chắc doFilter()phương pháp này hoạt động như thế nào ở đây. Bạn có thể vui lòng cho tôi biết làm thế nào để thực hiện điều này? Như trong, các bước chính xác để làm theo. Cảm ơn.
Anjan Baradwaj

Làm việc tốt cho tôi. Đã kiểm tra sau khi cả hai sendRedirect(...)forward().
Hal50000

5

* .jsp trong Mẫu Url sẽ không hoạt động nếu bạn chuyển tiếp một trang. Cố gắng bao gồm cả servlet của bạn .. điều đó sẽ giúp ứng dụng của bạn an toàn khỏi sự cố nút quay lại này.


2

Cách đơn giản nhất để làm điều đó mà không vô hiệu hóa trình duyệt quay lại buton là thêm mã này vào page_loadsự kiện cho trang mà bạn không muốn người dùng quay lại sau khi đăng xuất:

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
Mặc dù câu trả lời của bạn hữu ích, vui lòng đăng câu trả lời có liên quan đến ngôn ngữ lập trình OP lựa chọn. Giải pháp C # của bạn sẽ không giúp ích gì trong dự án Java EE của OP.
Buhake Sindi

0

Bạn có thể thử yêu cầu trình duyệt không lưu vào bộ đệm trang chủ (sử dụng các tiêu đề thích hợp - Expires, Cache-Control, Pragma). Nhưng nó không được đảm bảo để hoạt động. Những gì bạn có thể làm, là thực hiện một cuộc gọi ajax tới máy chủ khi tải trang để kiểm tra xem người dùng đã đăng nhập chưa và nếu chưa - chuyển hướng.


13
Nhưng nếu một ác tâm vô hiệu hóa JavaScript, điều này sẽ không hoạt động và anh ta sẽ thấy trang đó.
acme

0

Cách chính xác để làm điều này là thêm

Vary: Cookie

tiêu đề trên các trang bảo mật. Khi người dùng đăng xuất, hãy xóa cookie phiên của họ. Sau đó, khi họ điều hướng trở lại sau khi đăng xuất, bộ nhớ cache của trình duyệt sẽ bỏ lỡ. Điều này cũng có lợi ích là không đánh bại hoàn toàn bộ nhớ đệm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.