[转] Spring MVC实现token防止重复提交

转载自 开源中国社区

 1 一:首先创建一个token处理类  ,这里的类名叫 TokenHandler
 2  
 3 private static Logger logger = Logger.getLogger(TokenHandler.class);
 4  
 5     static Map<String, String> springmvc_token = null;
 6      
 7         //生成一个唯一值的token
 8     @SuppressWarnings("unchecked")
 9     public synchronized static String generateGUID(HttpSession session) {
10         String token = "";
11         try {
12             Object obj =  session.getAttribute("SPRINGMVC.TOKEN");
13             if(obj!=null)
14                 springmvc_token = (Map<String,String>)session.getAttribute("SPRINGMVC.TOKEN");
15            else
16                springmvc_token = new HashMap<String, String>()
17             token = new BigInteger(165, new Random()).toString(36)
18                     .toUpperCase();
19             springmvc_token.put(Constants.DEFAULT_TOKEN_NAME + "." + token,token);
20             session.setAttribute("SPRINGMVC.TOKEN", springmvc_token);
21             Constants.TOKEN_VALUE = token;
22  
23         } catch (IllegalStateException e) {
24             logger.error("generateGUID() mothod find bug,by token session...");
25         }
26         return token;
27     }
28  
29        //验证表单token值和session中的token值是否一致
30     @SuppressWarnings("unchecked")
31     public static boolean validToken(HttpServletRequest request) {
32         String inputToken = getInputToken(request);
33  
34         if (inputToken == null) {
35             logger.warn("token is not valid!inputToken is NULL");
36             return false;
37         }
38  
39         HttpSession session = request.getSession();
40         Map<String, String> tokenMap = (Map<String, String>)           session.getAttribute("SPRINGMVC.TOKEN");
41         if (tokenMap == null || tokenMap.size() < 1) {
42             logger.warn("token is not valid!sessionToken is NULL");
43             return false;
44         }
45         String sessionToken = tokenMap.get(Constants.DEFAULT_TOKEN_NAME + "."
46                 + inputToken);
47         if (!inputToken.equals(sessionToken)) {
48             logger.warn("token is not valid!inputToken='" + inputToken
49                     + "',sessionToken = '" + sessionToken + "'");
50             return false;
51         }
52         tokenMap.remove(Constants.DEFAULT_TOKEN_NAME + "." + inputToken);
53         session.setAttribute("SPRINGMVC.TOKEN", tokenMap);
54  
55         return true;
56     }
57  
58         //获取表单中token值
59     @SuppressWarnings("unchecked")
60     public static String getInputToken(HttpServletRequest request) {
61         Map params = request.getParameterMap();
62  
63         if (!params.containsKey(Constants.DEFAULT_TOKEN_NAME)) {
64             logger.warn("Could not find token name in params.");
65             return null;
66         }
67  
68         String[] tokens = (String[]) (String[]) params
69                 .get(Constants.DEFAULT_TOKEN_NAME);
70  
71         if ((tokens == null) || (tokens.length < 1)) {
72             logger.warn("Got a null or empty token name.");
73             return null;
74         }
75  
76         return tokens[0];
77     }
 1 二: 自己实现一个自定义标签 这里我自定义的标签叫: <dy:token/>  (自定义标签的代码实现,我放csdn上了,不会的赶紧去下载,这里我不讲了),页面中使用如下:
 2 1:引入标签库:<%@ taglib prefix="dy" uri="/dy-tags"%> 
 3 2:jsp页面中的表单,注意加上token标签!!!如下:
 4  
 5 index.jsp!!!
 6  
 7 <%@ taglib prefix="dy" uri="/dy-tags"%>
 8 <html>
 9   <head>
10     <title>spring mvc</title>
11   </head>
12   <body>          
13   welcome to spring mvc!<br/>
14  
15   <form name="mvcForm" action="indexSubmit.do" method="post">
16   <dy:token/>
17      username: <input name="username" type="text" value="${user.username}"/>
18      password: <input name="password" type="text" value="${user.password}"/>
19      email: <input name="email" type="text" value="${user.email}"/>
20        <input type="submit" value="提交">
21   </form>
22   </body>
23 </html>
 1 四: 我MyController类的以下2个方法要用到token,防止表单重复提交
 2  
 3 @RequestMapping(value = "index.do")
 4     public String index(HttpServletRequest request) {
 5          
 6         return "index";
 7     }
 8  
 9  
10 @RequestMapping(value = "indexSubmit.do", method = RequestMethod.POST)
11     public String indexSubmit(User user,HttpServletRequest request) {
12  
13         try {
14             myService.insert(user);
15             logger.info("info=新增成功");
16         } catch (Exception e) {
17             logger.error("exception:" + e);
18         }
 1 五:以下是我拦截器的实现,注意有两个拦截器,一个生成token,一个验证token。
 2 /**
 3  * @Title
 4  * @author dengyang
 5  * @date 2013-6-4
 6  */
 7 public class TokenHandlerInterceptor implements HandlerInterceptor{
 8  
 9  
10     public void afterCompletion(HttpServletRequest arg0,
11             HttpServletResponse arg1, Object arg2, Exception arg3)
12             throws Exception {
13     }
14  
15     public void postHandle(HttpServletRequest request, HttpServletResponse response,
16             Object arg2, ModelAndView arg3) throws Exception {
17         TokenHandler.generateGUID(request.getSession());
18     }
19  
20     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
21             Object arg2) throws Exception {
22         return true;
23     }
24  
25 }
26  
27  
28  
29 /**
30  * @Title
31  * @author dengyang
32  * @date 2013-6-4
33  */
34 public class TokenValidInterceptor implements HandlerInterceptor{
35  
36     public void afterCompletion(HttpServletRequest request,
37             HttpServletResponse response, Object arg2, Exception arg3)
38             throws Exception {
39     }
40  
41     public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
42             Object arg2, ModelAndView arg3) throws Exception {
43          
44     }
45     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
46             Object arg2) throws Exception {
47         if(!TokenHandler.validToken(request)){
48             response.sendRedirect(Constants.DEFAULT_TOKEN_MSG_JSP);
49             return false;
50         }
51     return true;
52     }
53  
54 }
 1 六:ok,这下面是我的spring拦截器配置
 2  
 3 <mvc:interceptor>
 4             <mvc:mapping path="/index.do" />-->这个请求返回的是你有token的页面
 5             <bean class="com.dengyang.interceptor.TokenHandlerInterceptor" />
 6         </mvc:interceptor>
 7         <mvc:interceptor>
 8             <mvc:mapping path="/indexSubmit.do" />-->这个是提交请求
 9             <bean class="com.dengyang.interceptor.TokenValidInterceptor" />
10         </mvc:interceptor>
11  
12  
13 七:ok,总体实现原理和struts的token标签类似,有问题请至 开源中国社区 留言

转载自 开源中国社区

posted @ 2016-01-14 13:39  Loeis.G  阅读(419)  评论(0)    收藏  举报