我正在使用Struts2开发一个Web应用程序。用户登录,发出请求然后注销。
当用户点击“后退”按钮(注销后)时,他不应该看到之前登录的页面,这意味着我想禁止浏览器缓存。我为此目的添加了一个拦截器:
public class CachingHeadersInterceptor extends AbstractInterceptor{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
final ActionContext context = invocation.getInvocationContext();
HttpServletResponse response = (HttpServletResponse)context.get(StrutsStatics.HTTP_RESPONSE);
if(response!=null){
response.setHeader("Cache-control", "no-cache, no-store");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "-1");
}
return invocation.invoke();
}
}
此条目位于struts.xml
文件中:
<interceptors>
<interceptor name="cachingHeadersInterceptor" class="com.proconsulto.interceptor.CachingHeadersInterceptor"/>
<interceptor-stack name="defaultSecurityStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="cachingHeadersInterceptor"/>
</interceptor-stack>
</interceptors>
但是当我点击后退按钮退出后,我仍然可以访问该登录页面。
这里缺少什么代码?我已经按照在线教程编写了这段代码。
以下是异常跟踪:
WARNING: Unable to load config class com.proconsulto.interceptor.CachingHeadersInterceptor at interceptor - file:/C:/Users/AnkitaNallana/Desktop/OneMoreTime/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ProConsulto%20-%20Everything%20is%20fine%20-%20v16/WEB-INF/classes/struts.xml:21:117 probably due to a missing jar, which might be fine if you never plan to use the cachingHeadersInterceptor interceptor
Jul 08, 2014 3:21:26 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger error
SEVERE: Actual exception
Caught Exception while registering Interceptor class com.proconsulto.interceptor.CachingHeadersInterceptor - interceptor - file:/C:/Users/AnkitaNallana/Desktop/OneMoreTime/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ProConsulto%20-%20Everything%20is%20fine%20-%20v16/WEB-INF/classes/struts.xml:21:117
at org.apache.struts2.impl.StrutsObjectFactory.buildInterceptor(StrutsObjectFactory.java:77)
at com.opensymphony.xwork2.config.providers.InterceptorBuilder.constructInterceptorReference(InterceptorBuilder.java:70)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.lookupInterceptorReference(XmlConfigurationProvider.java:1101)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStack(XmlConfigurationProvider.java:919)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStacks(XmlConfigurationProvider.java:932)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptors(XmlConfigurationProvider.java:955)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:524)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:292)
at org.apache.struts2.config.StrutsXmlConfigurationProvider.loadPackages(StrutsXmlConfigurationProvider.java:112)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:250)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:429)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:473)
at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:51)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:273)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:254)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:372)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:98)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4584)
at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5262)
at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5257)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.ClassNotFoundException: com.proconsulto.interceptor.CachingHeadersInterceptor
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1523)
at com.opensymphony.xwork2.util.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:152)
at com.opensymphony.xwork2.ObjectFactory.getClassInstance(ObjectFactory.java:108)
at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:161)
at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:151)
at org.apache.struts2.impl.StrutsObjectFactory.buildInterceptor(StrutsObjectFactory.java:52)
... 26 more
更加确定我复制了&amp;粘贴包装&amp;班级名称十几次,我仍然不知道为什么我得到ClassNotFoundException
!
另一种方法是在每个页面上将其写为JSP <% response.setHeader("xxx","vvv") %>
标记。这非常乏味。我不想使用JS禁用它,因为这将是糟糕的用户体验。
我也注意到了另一件事。当我在几个JSP上使用<% response.setHeader("xxx","vvv") %>
标签,然后点击“返回”按钮时,会显示一个重新加载按钮(在Chrome上) - 如果点击它 - 登录数据会被提交并且可以查看再次登录页面。我该怎么办才能保存此登录数据以便重新提交?
如果有类似的问题我可能没有遇到过 - 请在评论中提及其中的链接。我找不到答案,所以我在这里问!
答案 0 :(得分:2)
示例总是比理论更好......
编辑:我只是向您展示演示。
package com.interceptors;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class CachingHeadersInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
public String intercept(ActionInvocation invocation) throws Exception {
if (ServletActionContext.getResponse() != null) {
ServletActionContext.getResponse().setHeader("Cache-control",
"no-cache, no-store, must-revalidate");
ServletActionContext.getResponse().setHeader("Pragma", "no-cache");
ServletActionContext.getResponse().setHeader("Expires", "-1");
ServletActionContext.getResponse().setHeader("Vary", "*");
}
return invocation.invoke();
}
}
在struts.xml
<package name="helloworld" namespace="" extends="struts-default">
<interceptors>
<interceptor name="cachingHeadersInterceptor" class="com.interceptors.CachingHeadersInterceptor"/>
<interceptor-stack name="defaultSecurityStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="cachingHeadersInterceptor"/>
</interceptor-stack>
</interceptors>
<action name="login" class="com.common.LoginAction" >
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="cachingHeadersInterceptor"/>
<result name="success">/Home.jsp</result>
</action>
</package>
输出:这是响应标题
注销后,如果您想阻止用户查看页面,您可以实施Authorizeinterceptor
参考:参见AuthorizationInterceptor.java
的示例在这个拦截器中,只需检查会话值,例如用户名,在注销后将为null,如果为null,则重定向到登录。
您可以创建新的拦截器,也可以将以下代码放在同一个CachingHeadersInterceptor.java
SessionMap<String,Object> map = (SessionMap<String,Object>) inv.getInvocationContext().getSession();
Object user = map.get("username");
if(user==null ||user.equals("") || map.isEmpty() || map == null ){
return "login";
}
在struts.xml
中将登录定义为重定向到登录页面的结果。
<global-results>
<result name="login">login.jsp</result>
</global-results>
另请参阅我已在会话中添加和删除用户名的LoginAction.java和LogoutAction.java。
这很简单.... :)
答案 1 :(得分:1)
您是否将以下内容放在html head标签中:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Pragma" content="No-cache" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Expires" content="0" />
同时确保在退出后删除了会话。