我要求最终用户在注销/注销后无法返回受限页面。但目前最终用户可以通过浏览器后退按钮访问浏览器历史记录,甚至可以在浏览器的地址栏中重新输入URL。
基本上,我希望最终用户在注销后无法以任何方式访问受限制的页面。我怎样才能做到最好?我可以使用JavaScript禁用后退按钮吗?
答案 0 :(得分:131)
您可以也不应该禁用浏览器后退按钮或历史记录。这对用户体验不利。有JavaScript攻击,但它们不可靠,当客户端禁用JS时也无法运行。
您的具体问题是所请求的页面是从浏览器缓存加载的,而不是直接从服务器加载的。这基本上是无害的,但确实让最终用户感到困惑,因为他/她错误地认为它确实来自服务器。
您只需要指示浏览器不缓存所有受限制的JSP页面(因此不仅仅是注销页面/操作本身!)。这样,浏览器被迫从服务器而不是从缓存请求页面,因此将执行服务器上的所有登录检查。您可以使用Filter设置doFilter()
方法中的necessary response headers来执行此操作:
@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
中执行此作业。
在测试之前不要忘记清除浏览器缓存! ;)
答案 1 :(得分:5)
*。如果您转发页面,则Url Pattern中的jsp将无效。尝试包括你的servlet ..这将使你的应用程序免受此后退按钮问题。
答案 2 :(得分:2)
在不停用浏览器的情况下执行此操作的最简单方法是将此代码添加到您不希望用户在注销后返回的页面的page_load
事件中: / p>
if (!IsPostBack)
{
if (Session["userId"] == null)
{
Response.Redirect("Login.aspx");
}
else
{
Response.ClearHeaders();
Response.AddHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
Response.AddHeader("Pragma", "no-cache");
}
}
答案 3 :(得分:0)
您可以尝试告诉浏览器不要缓存主页(使用适当的标题 - Expires,Cache-Control,Pragma)。但它不能保证工作。您可以做的是,在页面加载时对服务器进行ajax调用以检查用户是否已记录,如果没有 - 重定向。
答案 4 :(得分:0)
正确的方法是添加
Vary: Cookie
安全页面上的标题。当用户注销时,清除其会话cookie。然后,当他们在注销后导航回来时,浏览器缓存将会丢失。这也有不完全破坏缓存的好处。
答案 5 :(得分:0)
实现过滤器的另一种方法是在所有受保护的 JSP 或所有路径上设置“无缓存”过滤器。如果应用程序很小,并且您只想为特定页面自定义此属性,这可能是一个好主意。我们可以在每个不应缓存的安全 JSP 上添加以下 Java 片段:
<%
response.addHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setDateHeader("Expires", 0);
%>
如果不是在 JSP 上,这也可以用于定义路由并设置 'HttpServletResponse' 对象的标头的控制器中。