我要求最终用户在注销/注销后不能返回受限页面。但目前最终用户可以通过浏览器的后退按钮、访问浏览器历史记录甚至通过在浏览器的地址栏中重新输入 URL 来做到这一点。
基本上,我希望最终用户在退出后不能以任何方式访问受限页面。我怎样才能做到最好?我可以使用 JavaScript 禁用后退按钮吗?
我要求最终用户在注销/注销后不能返回受限页面。但目前最终用户可以通过浏览器的后退按钮、访问浏览器历史记录甚至通过在浏览器的地址栏中重新输入 URL 来做到这一点。
基本上,我希望最终用户在退出后不能以任何方式访问受限页面。我怎样才能做到最好?我可以使用 JavaScript 禁用后退按钮吗?
您可以而且不应该禁用浏览器后退按钮或历史记录。这对用户体验很不利。有 JavaScript hack,但它们不可靠,并且在客户端禁用 JS 时也无法工作。
您的具体问题是请求的页面是从浏览器缓存加载的,而不是直接从服务器加载的。这本质上是无害的,但确实让最终用户感到困惑,因为他/她错误地认为它确实来自服务器。
您只需要指示浏览器不要缓存所有受限制的 JSP 页面(因此不仅仅是注销页面/操作本身!)。这样,浏览器被迫从服务器而不是从缓存中请求页面,因此将执行服务器上的所有登录检查。您可以使用在方法中设置必要的响应标头的过滤器来执行此操作:doFilter()
@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);
}
// ...
}
将其映射Filter
到url-pattern
感兴趣的对象上,例如*.jsp
。
@WebFilter("*.jsp")
或者,如果您只想将此限制放在受保护的页面上,那么您应该指定一个涵盖所有这些受保护页面的 URL 模式。例如,当它们都在文件夹中时/app
,则需要指定/app/*
.
@WebFilter("/app/*")
更重要的是,您可以Filter
像检查登录用户的存在一样完成这项工作。
测试前不要忘记清除浏览器缓存!;)
如果您转发页面,Url Pattern 中的 *.jsp 将不起作用。尝试也包含您的 servlet。这将使您的应用程序免受此后退按钮问题的影响。
在不禁用浏览器返回按钮的情况下执行此操作的最简单方法是将此代码添加到page_load
您不希望用户在注销后返回的页面的事件中:
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");
}
}
正确的方法是添加
Vary: Cookie
安全页面上的标题。当用户注销时,清除他们的会话 cookie。然后,当他们在注销后导航回来时,浏览器缓存将丢失。这还具有不完全破坏缓存的好处。
您可以尝试告诉浏览器不要缓存主页(使用适当的标头 - Expires、Cache-Control、Pragma)。但不保证能正常工作。您可以做的是在页面加载时对服务器进行 ajax 调用,以检查用户是否已登录,如果没有 - 重定向。
实现过滤器的另一种方法是在所有受保护的 JSP 或所有路径上设置“无缓存”过滤器。如果应用程序很小,并且您只想为特定页面自定义此属性,这可能是一个好主意。我们可以在每个不应缓存的安全 JSP 上添加以下 Java 片段:
<%
response.addHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setDateHeader("Expires", 0);
%>
如果不在 JSP 上,这也可以在定义了路由并设置“HttpServletResponse”对象的标头的控制器中使用。
对我来说,问题是,我不想在所有页面上设置标题,所以我只是在单击注销时在页面上设置这个标题,它会清除与网站相关的所有内容:)
// Removes all site data
response.setHeader ("Clear-Site-Data", "\"cache\"");
请在此处阅读有关它的更多信息: https ://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data