分享

springmvc中自己实现的token防表单重复提交,防止二次提交

 KILLKISS 2014-05-16

代码简介

springmvc中自己实现的token防表单重复提交,防止二次提交!!!

代码片段

一:首先创建一个token处理类  ,这里的类名叫 TokenHandler

private static Logger logger = Logger.getLogger(TokenHandler.class);

	static Map<String, String> springmvc_token = new HashMap<String, String>();
	
        //生成一个唯一值的token
	@SuppressWarnings("unchecked")
	public synchronized static String generateGUID(HttpSession session) {
		String token = "";
		try {
			Object obj =  session.getAttribute("SPRINGMVC.TOKEN");
			if(obj!=null)
				springmvc_token = (Map<String,String>)session.getAttribute("SPRINGMVC.TOKEN");
			token = new BigInteger(165, new Random()).toString(36)
					.toUpperCase();
			springmvc_token.put(Constants.DEFAULT_TOKEN_NAME + "." + token,token);
			session.setAttribute("SPRINGMVC.TOKEN", springmvc_token);
			Constants.TOKEN_VALUE = token;

		} catch (IllegalStateException e) {
			logger.error("generateGUID() mothod find bug,by token session...");
		}
		return token;
	}

       //验证表单token值和session中的token值是否一致
	@SuppressWarnings("unchecked")
	public static boolean validToken(HttpServletRequest request) {
		String inputToken = getInputToken(request);

		if (inputToken == null) {
			logger.warn("token is not valid!inputToken is NULL");
			return false;
		}

		HttpSession session = request.getSession();
		Map<String, String> tokenMap = (Map<String, String>)           session.getAttribute("SPRINGMVC.TOKEN");
		if (tokenMap == null || tokenMap.size() < 1) {
			logger.warn("token is not valid!sessionToken is NULL");
			return false;
		}
		String sessionToken = tokenMap.get(Constants.DEFAULT_TOKEN_NAME + "."
				+ inputToken);
		if (!inputToken.equals(sessionToken)) {
			logger.warn("token is not valid!inputToken='" + inputToken
					+ "',sessionToken = '" + sessionToken + "'");
			return false;
		}
		tokenMap.remove(Constants.DEFAULT_TOKEN_NAME + "." + inputToken);
		session.setAttribute("SPRINGMVC.TOKEN", tokenMap);

		return true;
	}

        //获取表单中token值
	@SuppressWarnings("unchecked")
	public static String getInputToken(HttpServletRequest request) {
		Map params = request.getParameterMap();

		if (!params.containsKey(Constants.DEFAULT_TOKEN_NAME)) {
			logger.warn("Could not find token name in params.");
			return null;
		}

		String[] tokens = (String[]) (String[]) params
				.get(Constants.DEFAULT_TOKEN_NAME);

		if ((tokens == null) || (tokens.length < 1)) {
			logger.warn("Got a null or empty token name.");
			return null;
		}

		return tokens[0];
	}

代码片段

三 :这是我用到的常量:
public static String DEFAULT_TOKEN_MSG_JSP = "unSubmit.jsp" ;
	public static String TOKEN_VALUE ;
	public static String DEFAULT_TOKEN_NAME = "springMVC.token";

代码片段

二: 自己实现一个自定义标签 这里我自定义的标签叫: <dy:token/>  (自定义标签的代码实现,我放csdn上了,不会的赶紧去下载,这里我不讲了),页面中使用如下:
1:引入标签库:<%@ taglib prefix="dy" uri="/dy-tags"%> 
2:jsp页面中的表单,注意加上token标签!!!如下:

index.jsp!!!

<%@ taglib prefix="dy" uri="/dy-tags"%>
<html>
  <head>
    <title>spring mvc</title>
  </head>
  <body>          
  welcome to spring mvc!<br/>

  <form name="mvcForm" action="indexSubmit.do" method="post">
  <dy:token/>
     username: <input name="username" type="text" value="${user.username}"/>
     password: <input name="password" type="text" value="${user.password}"/>
     email: <input name="email" type="text" value="${user.email}"/>
       <input type="submit" value="提交">
  </form>
  </body>
</html>

代码片段

四: 我MyController类的以下2个方法要用到token,防止表单重复提交

@RequestMapping(value = "index.do")
	public String index(HttpServletRequest request) {
		
		return "index";
	}


@RequestMapping(value = "indexSubmit.do", method = RequestMethod.POST)
	public String indexSubmit(User user,HttpServletRequest request) {

		try {
			myService.insert(user);
			logger.info("info=新增成功");
		} catch (Exception e) {
			logger.error("exception:" + e);
		}

代码片段

五:以下是我拦截器的实现,注意有两个拦截器,一个生成token,一个验证token。
/**
 * @Title
 * @author dengyang
 * @date 2013-6-4
 */
public class TokenHandlerInterceptor implements HandlerInterceptor{


	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response,
			Object arg2, ModelAndView arg3) throws Exception {
		TokenHandler.generateGUID(request.getSession());
	}

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			Object arg2) throws Exception {
		return true;
	}

}



/**
 * @Title
 * @author dengyang
 * @date 2013-6-4
 */
public class TokenValidInterceptor implements HandlerInterceptor{

	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object arg2, Exception arg3)
			throws Exception {
	}

	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		
	}
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			Object arg2) throws Exception {
		if(!TokenHandler.validToken(request)){
			response.sendRedirect(Constants.DEFAULT_TOKEN_MSG_JSP);
			return false;
		}
	return true;
	}

}

代码片段

六:ok,这下面是我的spring拦截器配置

<mvc:interceptor>
			<mvc:mapping path="/index.do" />-->这个请求返回的是你有token的页面
			<bean class="com.dengyang.interceptor.TokenHandlerInterceptor" />
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/indexSubmit.do" />-->这个是提交请求
			<bean class="com.dengyang.interceptor.TokenValidInterceptor" />
		</mvc:interceptor>


七:ok,总体实现原理和struts的token标签类似,有问题请留言...

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多