spring mvc基于token防止重复提交验证

spring mvc基于token防止重复提交验证

实现思路:

在springmvc配置文件中加入拦截器的配置,拦截两类请求,一类是到页面的,一类是提交表单的。当转到页面的请求到来时,生成token的名字和token值,放入session,在页面表单的隐藏域显示。

当表单请求提交时,拦截器得到参数中的tokenName和token,然后到session中去取token值,如果能匹配上,请求就通过,不能匹配上就不通过。这里的token生成时也是随机的,每次请求都不一样。而从session中取token值时,会立即将其删除(删与读是原子的,无线程安全问题)。

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

[java]  view plain  copy
  1. package com.base.utils;  
  2. import java.math.BigInteger;  
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5. import java.util.Random;  
  6.   
  7. import javax.servlet.http.HttpServletRequest;  
  8. import javax.servlet.http.HttpSession;  
  9.   
  10. import org.apache.log4j.Logger;  
  11.   
  12. /** 
  13.  * 创建时间:2017年4月5日 下午5:56:31  
  14.  * 项目名称:tra02 
  15.  *  
  16.  * @author hc 
  17.  * @version 1.0  
  18.  * 文件名称:TokenHandler.java  
  19.  * 类说明: 
  20.  */  
  21. public class TokenHandler {  
  22.     private static Logger logger = Logger.getLogger(TokenHandler.class);  
  23.   
  24.     static Map<String, String> springmvc_token = null;  
  25.   
  26.     // 生成一个唯一值的token  
  27.     @SuppressWarnings("unchecked")  
  28.     public synchronized static String generateGUID(HttpSession session) {  
  29.         String token = "";  
  30.         try {  
  31.             Object obj = session.getAttribute("SPRINGMVC.TOKEN");  
  32.             if (obj != null)  
  33.                 springmvc_token = (Map<String, String>) session.getAttribute("SPRINGMVC.TOKEN");  
  34.             else  
  35.                 springmvc_token = new HashMap<String, String>();  
  36.             token = new BigInteger(165new Random()).toString(36).toUpperCase();  
  37.             springmvc_token.put(Constants.DEFAULT_TOKEN_NAME + "." + token, token);  
  38.             session.setAttribute("SPRINGMVC.TOKEN", springmvc_token);  
  39.             Constants.TOKEN_VALUE = token;  
  40.             // System.out.println(session.getAttribute("SPRINGMVC.TOKEN"));  
  41.         } catch (IllegalStateException e) {  
  42.             logger.error("generateGUID() mothod find bug,by token session...");  
  43.         }  
  44.         return token;  
  45.     }  
  46.   
  47.     // 验证表单token值和session中的token值是否一致  
  48.     @SuppressWarnings("unchecked")  
  49.     public static boolean validToken(HttpServletRequest request) {  
  50.         String inputToken = getInputToken(request);  
  51.   
  52.         if (inputToken == null) {  
  53.             logger.warn("令牌是不是有效的。inputtoken是空的");  
  54.             return false;  
  55.         }  
  56.   
  57.         HttpSession session = request.getSession();  
  58.         Map<String, String> tokenMap = (Map<String, String>) session.getAttribute("SPRINGMVC.TOKEN");  
  59.         if (tokenMap == null || tokenMap.size() < 1) {  
  60.             logger.warn("token is not valid!sessionToken is NULL");  
  61.             return false;  
  62.         }  
  63.         String sessionToken = tokenMap.get(Constants.DEFAULT_TOKEN_NAME + "." + inputToken);  
  64.         if (!inputToken.equals(sessionToken)) {  
  65.             logger.warn("token is not valid!inputToken='" + inputToken + "',sessionToken = '" + sessionToken + "'");  
  66.             return false;  
  67.         }  
  68.         tokenMap.remove(Constants.DEFAULT_TOKEN_NAME + "." + inputToken);  
  69.         session.setAttribute("SPRINGMVC.TOKEN", tokenMap);  
  70.   
  71.         return true;  
  72.     }  
  73.   
  74.     // 获取表单中token值  
  75.     @SuppressWarnings("unchecked")  
  76.     public static String getInputToken(HttpServletRequest request) {  
  77.         Map params = request.getParameterMap();  
  78.         System.out.println(request.getSession().getAttribute("SPRINGMVC.TOKEN"));  
  79.         if (!params.containsKey(Constants.DEFAULT_TOKEN_NAME)) {  
  80.             logger.warn("无法找到令牌名称参数。");  
  81.             return null;  
  82.         }  
  83.   
  84.         String[] tokens = (String[]) (String[]) params.get(Constants.DEFAULT_TOKEN_NAME);  
  85.   
  86.         if ((tokens == null) || (tokens.length < 1)) {  
  87.             logger.warn("得到空或空的令牌名称。");  
  88.             return null;  
  89.         }  
  90.         String temp = tokens[0];  
  91.         String inputtoken = temp.substring(temp.indexOf("=") + 1, (temp.length()) - 1);  
  92.         return inputtoken;  
  93.     }  
  94. }  

二、建立常量配置类Constabts

[java]  view plain  copy
  1. package com。base.utils;  
  2.   
  3. /** 
  4.  * 创建时间:2017年4月5日 下午5:57:58  
  5.  * 项目名称:traffic02 
  6.  *  
  7.  * @author hc 
  8.  * @version 1.0  
  9.  * 文件名称:Constants.java  
  10.  * 类说明: 
  11.  */  
  12. public class Constants {  
  13.       
  14.     public static String DEFAULT_TOKEN_MSG_JSP = "add.jsp";  
  15.     public static String TOKEN_VALUE;  
  16.     public static String DEFAULT_TOKEN_NAME = "springMVC.token";  
  17.       
  18. }  

三、前端页面 主要是隐藏域

[html]  view plain  copy
  1. <%@page import="java.util.Map"%>  
  2. <%@ page language="java" contentType="text/html; charset=utf-8"  
  3.     pageEncoding="utf-8"%>  
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  5. <html>  
  6. <head>  
  7. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
  8. <title>Insert title here</title>  
  9. </head>  
  10. <body>  
  11.     <div align="center">  
  12.     <form action="user/add" method="post" >  
  13.       
  14.     <input type="hidden" name="springMVC.token" value="<%=session.getAttribute("SPRINGMVC.TOKEN")%>>  
  15.     名字:<input type="text" name="username">  
  16.     密码:<input type="password" name="password"/>  
  17.     <input type="submit" value="提交">  
  18.     </form>  
  19.       
  20.     </div>  
  21. </body>  
  22. </html>  

四、controller不用多写什么,能跳转举行

[java]  view plain  copy
  1. package com.traffic.controller;  
  2.   
  3. import org.springframework.stereotype.Controller;  
  4. import org.springframework.ui.Model;  
  5. import org.springframework.web.bind.annotation.RequestMapping;  
  6.   
  7. /**   
  8. * 创建时间:2017年4月5日 下午1:43:00   
  9. * 项目名称:tra   
  10. * @author hc   
  11. * @version 1.0    
  12. * 文件名称:UserController.java   
  13. * 类说明:   
  14. */  
  15. @Controller  
  16. @RequestMapping("/user")  
  17. public class UserController {  
  18.       
  19.     @RequestMapping("/toadd")  
  20.     public String toadd(Model model){  
  21.           
  22.         return "forward:/add.jsp";  
  23.     }  
  24.       
  25.     @RequestMapping("/add")  
  26.     public String add(String username,String password,Model model){  
  27.           
  28.         System.out.println("suc");  
  29.         return "forward:/suc.jsp";  
  30.     }  
  31. }  
  32.    
五、重点是拦截器 一个生成token,一个验证token。

[java]  view plain  copy
  1. public class TokenHandlerInterceptor implements HandlerInterceptor{  
  2.    
  3.    
  4.     public void afterCompletion(HttpServletRequest arg0,  
  5.             HttpServletResponse arg1, Object arg2, Exception arg3)  
  6.             throws Exception {  
  7.     }  
  8.    
  9.     public void postHandle(HttpServletRequest request, HttpServletResponse response,  
  10.             Object arg2, ModelAndView arg3) throws Exception {  
  11.         TokenHandler.generateGUID(request.getSession());  
  12.     }  
  13.    
  14.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
  15.             Object arg2) throws Exception {  
  16.         return true;  
  17.     }  
  18.    
  19. }  
  20.    
  21.    
  22.    
  23. /** 
  24.  * @Title 
  25.  * @author  
  26.  * @date  
  27.  */  
  28. public class TokenValidInterceptor implements HandlerInterceptor{  
  29.    
  30.     public void afterCompletion(HttpServletRequest request,  
  31.             HttpServletResponse response, Object arg2, Exception arg3)  
  32.             throws Exception {  
  33.     }  
  34.    
  35.     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,  
  36.             Object arg2, ModelAndView arg3) throws Exception {  
  37.            
  38.     }  
  39.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
  40.             Object arg2) throws Exception {  
  41.         if(!TokenHandler.validToken(request)){  
  42.             response.sendRedirect(Constants.DEFAULT_TOKEN_MSG_JSP);  
  43.             return false;  
  44.         }  
  45.     return true;  
  46.     }  
  47.    
  48. }  

六、当然 springmvc要配置拦截器

[html]  view plain  copy
  1. <mvc:interceptor>  
  2.             <mvc:mapping path="/index.do" />-->这个请求返回的是你有token的页面  
  3.             <bean class="com.dengyang.interceptor.TokenHandlerInterceptor" />  
  4.         </mvc:interceptor>  
  5.         <mvc:interceptor>  
  6.             <mvc:mapping path="/indexSubmit.do" />-->这个是提交请求  
  7.             <bean class="com.dengyang.interceptor.TokenValidInterceptor" />  
  8.         </mvc:interceptor>  
  9.    

七、本方案如果不足之处,请大神们指教;

声明:本方案源于

http://www.oschina.net/code/snippet_100825_21906  

本人做了一些修改



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值