<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          springmvc 用攔截器 +token 防止重復(fù)提交

          共 3626字,需瀏覽 8分鐘

           ·

          2018-10-16 02:14

          ? 首先,防止用戶重復(fù)提交有很多種方式,總體分為前端JS限制和后端限制,我個(gè)人認(rèn)為后端限制比較妥當(dāng)(本著能做到更優(yōu)秀得理念,舍去了前端JS限制重復(fù)提交得想法).

            之前沒(méi)有做過(guò)防止用戶重復(fù)提交,所以直接百度了一大堆,竟然發(fā)現(xiàn)基本上可以歸為2到3種真正不同實(shí)現(xiàn)得代碼,文章雖然有很多,不過(guò)大部分代碼幾乎都出自同一人,原文網(wǎng)址:http://blog.icoolxue.com/submitted-by-spring-mvc-to-prevent-data-duplication/,想著這么多人用代碼應(yīng)該沒(méi)問(wèn)題,所以該復(fù)制復(fù)制,該手建手建,終于大工搞成,但是測(cè)試得時(shí)候發(fā)現(xiàn)了一個(gè)很重要得問(wèn)題,永遠(yuǎn)處于重復(fù)提交狀態(tài),我得天啊,這就很尷尬了,于是趕緊打斷點(diǎn),F(xiàn)6F6F6,終于懷疑了一行代碼,貼代碼:

           private boolean isRepeatSubmit(HttpServletRequest request) {
                  String serverToken = (String) request.getSession(true).getAttribute("token");
                  if (serverToken == null) {
                      return true;
                  }
                  String clinetToken = request.getParameter("token");//就是這行 NULL,永遠(yuǎn)是NULL。
                  if (clinetToken == null) {
                      return true;
                  }
                  if (!serverToken.equals(clinetToken)) {
                      return true;
                  }
                  return false;
              }


          嘿我就那了悶,怎么會(huì)接收不到值呢?肯定是頁(yè)面有問(wèn)題了,頁(yè)面就只有一句話



          我突然腦袋靈光一閃,通過(guò)name值傳值必須在form表單里才行,我全是AJAX啊,于是趕緊在傳遞參數(shù)中加上token,問(wèn)題也就順利得結(jié)果了!

          但是我就再想,這么多人復(fù)制原文得代碼,然后發(fā)到自己得博客,難道沒(méi)有出現(xiàn)這種問(wèn)題嘛?

          問(wèn)題解決了,順便總結(jié)一下token得使用方法,切記代碼沒(méi)問(wèn)題,復(fù)制需謹(jǐn)慎(該改得記得改!)

          首先自定義一個(gè)注解:

          package com.dinfo.interceptor;
          
          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;
          import java.lang.annotation.Target;
          
          @Target(ElementType.METHOD)
          @Retention(RetentionPolicy.RUNTIME)
          public @interface Token {
          
              boolean save() default false;
          
              boolean remove() default false;
          }

          接著實(shí)現(xiàn)一個(gè)攔截器借口:

          package com.dinfo.interceptor;
          
          import java.lang.reflect.Method;
          import java.util.UUID;
          
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          import org.apache.log4j.Logger;
          import org.springframework.web.method.HandlerMethod;
          import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
          
          public class TokenInterceptor extends HandlerInterceptorAdapter {
              private static final Logger LOG = Logger.getLogger(Token.class);
              @Override
              public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                  if (handler instanceof HandlerMethod) {
                      HandlerMethod handlerMethod = (HandlerMethod) handler;
                      Method method = handlerMethod.getMethod();
                      Token annotation = method.getAnnotation(Token.class);
                      if (annotation != null) {
                          boolean needSaveSession = annotation.save();
                          if (needSaveSession) {
                              request.getSession(true).setAttribute("token", UUID.randomUUID().toString());
                          }
                          boolean needRemoveSession = annotation.remove();
                          if (needRemoveSession) {
                              if (isRepeatSubmit(request)) {
                                   LOG.warn("please don't repeat submit,url:"+ request.getServletPath());
                                  return false;
                              }
                              request.getSession(true).removeAttribute("token");
                          }
                      }
                      return true;
                  } else {
                      return super.preHandle(request, response, handler);
                  }
              }
          
              private boolean isRepeatSubmit(HttpServletRequest request) {
                  String serverToken = (String) request.getSession(true).getAttribute("token");
                  if (serverToken == null) {
                      return true;
                  }
                  String clinetToken = request.getParameter("token");
                  if (clinetToken == null) {
                      return true;
                  }
                  if (!serverToken.equals(clinetToken)) {
                      return true;
                  }
                  return false;
              }
          }

          最后是配置文件:

          
          
                  
                  
                      
                      
                  
          
                  
          

          最最最重要得一點(diǎn)一定要保證頁(yè)面和后臺(tái)token得正常傳遞?。。?/p>

          在需要生成token(通常是要點(diǎn)擊提交得那個(gè)頁(yè)面)得Controller中使用我們剛才自定義好得注解,貼代碼:

              @SuppressWarnings({ "unchecked", "finally", "rawtypes" })
              @RequestMapping("/SaveDataController/show")
              @Token(save=true)
              public String saveData(HttpServletRequest request,HttpServletResponse response,String task_id){
                  
                  Map map = new HashMap();
                  System.out.println(task_id);
                  try {
                      map = saveDataService.queryByTaskId(task_id);
                  } catch (Exception e) {
                      e.printStackTrace();
                      map.put("task_id", task_id);
                      map.put("savetype", "");
                      map.put("memoryCodes", "1");
                      map.put("tablename", "");
                      map.put("trowkey", "");
                      map.put("columns", "");
                      map.put("indextablename", "");
                      map.put("irowkey", "");
                      map.put("icolumns", "");
                  } finally {
                      request.setAttribute("map", map);
                      return "savedata/index";
                  }
              }

          只要通過(guò)這個(gè)方法跳向得頁(yè)面都是隨機(jī)生成一個(gè)token,然后再真正再提交觸發(fā)得方法上加入@token(remove=true),貼代碼:

          @RequestMapping("/SaveDataController/saveData")
              @ResponseBody
              @Token(remove=true)
              public void saveData(HttpServletRequest request,HttpServletResponse response,
                                   String tablename,String trowkey,String columns,
                                   String indextablename,String irowkey,String icolumns,
                                   String task_id,String savetype,String memoryCodes){
                  System.out.println(task_id);
                  saveDataService.saveData(task_id,savetype,memoryCodes,tablename, trowkey, columns, indextablename, irowkey, icolumns);
              }

          OK,到這里大功告成,你就可以發(fā)現(xiàn)已經(jīng)沒(méi)有辦法重復(fù)提交數(shù)據(jù)了!有問(wèn)題可以隨時(shí)找我溝通。

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线操逼喷水 | 猛操人妻| 操逼视频手机播放 | 成人AV导航 | 一级A片逼|