浏览 3772 次
锁定老帖子 主题:通过xml配置搞定Struts重复提交问题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-12-15
核心代码如下: package com.yapulan.util.filter; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.servlet.Filter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.FilterConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.FilterChain; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.log4j.Logger; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * 重复提交令牌自动加载器 功能:读取过滤器中设置的信息,读入令牌设置组 */ public class TokenFilter implements Filter { private String TokenConfig = "TokenConfig.xml"; private HashMap TokenMap = null; private HashMap ErrorMap = null; protected FilterConfig filterConfig; static Logger logger = Logger.getLogger(TokenFilter.class.getName()); public void init(FilterConfig config) throws ServletException { this.filterConfig = config; this.TokenConfig = config.getInitParameter("tokenfile"); logger.debug("Tokenlist init OK!"); } /** * 初始化系统的xml文件,读入令牌列表 */ @SuppressWarnings({ "unchecked", "deprecation" }) public void initConfig(ServletRequest srequest) { HttpServletRequest httpRequest = (HttpServletRequest) srequest; try { TokenMap = new HashMap(); ErrorMap = new HashMap(); SAXReader reader = new SAXReader(); Document document = reader.read(httpRequest.getRealPath(this.TokenConfig)); List list1 = document.getRootElement().selectNodes("/TokenList/Token/TokenForm"); List list2 = document.getRootElement().selectNodes("/TokenList/Token/TokenAction"); List list3 = document.getRootElement().selectNodes("/TokenList/Token/ErrorPage"); Iterator iter1 = list1.iterator(); Iterator iter2 = list2.iterator(); Iterator iter3 = list3.iterator(); while (iter1.hasNext()&&iter2.hasNext()&&iter3.hasNext()) { Element element1 = (Element) iter1.next(); Element element2 = (Element) iter2.next(); Element element3 = (Element) iter3.next(); TokenMap.put(element1.getStringValue(), element2.getStringValue()); ErrorMap.put(element1.getStringValue(), element3.getStringValue()); } logger.debug("TokenFilter Read " + httpRequest.getRealPath(this.TokenConfig) + " is OK!"); } catch (Exception e) { logger.error("TokenFilter Read " + httpRequest.getRealPath(this.TokenConfig) + " is Error!"); } } public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) srequest; try { //取出实际的文件路径直接调用文件,如index.html,login.jsp等 String toURI = httpRequest.getRequestURI().replaceFirst(httpRequest.getContextPath(), ""); if (TokenMap==null) { initConfig(httpRequest); } //检测为提交jsp页 if (TokenMap.get(toURI) != null) { FromTokenAction token = new FromTokenAction(); token.execute(null, null, srequest, sresponse); httpRequest.getSession().setAttribute("PRE_TOKEN_FORM", toURI); logger.debug("TokenFilter save '"+toURI +"' at 'PRE_TOKEN_FORM' of Session!"); logger.debug("TokenFilter saveToken to '"+toURI +"' is OK!"); chain.doFilter(srequest, sresponse); return; } @SuppressWarnings("unused") String preURI =(String)httpRequest.getSession().getAttribute("PRE_TOKEN_FORM"); //检测到为Action接收提交页面 if (TokenMap.get(preURI).equals(toURI)) { TOTokenAction token = new TOTokenAction(); token.execute(null, null, srequest, sresponse); chain.doFilter(srequest, sresponse); return; } } catch (Exception e) { logger.error(e); } chain.doFilter(srequest, sresponse); } public void setFilterConfig(final FilterConfig filterConfig) { this.filterConfig = filterConfig; } public void destroy() { TokenMap.clear(); ErrorMap.clear(); this.filterConfig = null; } //检测到需要令牌增加一个令牌 public class FromTokenAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { this.saveToken(request); return null; } } //到达Action前检测令牌 public class TOTokenAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { @SuppressWarnings("unused") String preURI =(String)request.getSession().getAttribute("PRE_TOKEN_FORM"); //如果检测令牌错误执行错误页,正确将继续执行 if (!isTokenValid(request, true)) { @SuppressWarnings("unused") String toURI = (String)ErrorMap.get(preURI); if (toURI!=null) { RequestDispatcher disp = request.getRequestDispatcher(toURI); try { disp.forward(request, response); }catch(Exception e) { logger.error(e); } } } return null; } } } Web.xml的配制 <!-- 令牌自动加载配制 --> <filter> <filter-name>tokenFilter</filter-name> <filter-class>com.yapulan.util.filter.TokenFilter</filter-class> <init-param> <param-name>tokenfile</param-name> <param-value>/WEB-INF/TokenConfig.xml</param-value> </init-param> </filter> 注意:将代码包中web.xml做以下修改 <filter-mapping> <filter-name>tokenFilter</filter-name> <url-pattern/*</url-pattern> </filter-mapping> 设置好过滤器,只要配置列表即可避免所有的重复提交问题,不必在编程时再次考虑了 <?xml version="1.0" encoding="UTF-8"?> <TokenList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="TokenConfig.xsd"> <Token> <TokenForm>/index.jsp</TokenForm> <TokenAction>/TokenAction.do</TokenAction> <ErrorPage>/error.html</ErrorPage> </Token> <Token> <TokenForm>/index1.jsp</TokenForm> <TokenAction>/TokenAction1.do</TokenAction> <ErrorPage>/error1.jsp</ErrorPage> </Token> <Token> <TokenForm>/index2.jsp</TokenForm> <TokenAction>/TokenAction2.do</TokenAction> <ErrorPage>/error2.jsp</ErrorPage> </Token> <Token> <TokenForm>/index3.jsp</TokenForm> <TokenAction>/TokenAction3.do</TokenAction> <ErrorPage>/error3.jsp</ErrorPage> </Token> </TokenList> 注意:本代码可以很好的验证非法的提交,对于管理非法的提交是一个不可多得的具有一定安全意义封装。 请热心的朋友分析有无其它没有考虑的细节问题,并且是否有可以进一部完善的地方,谢谢! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |