一,原理:
1,在進入到提交頁面時,使用攔截器攔截在進入此方法前,生成一個token,放到session中,
@RequestMapping(value = "/{id}/details") @FormToken(produce = true) public Object details(@PathVariable String id, HttpServletRequest request){ Map<String,Object> map = new HashMap<>(); GameInfo gameInfo; int count; try { gameInfo = gameInfoService.get(id, -1); // 使用此游戲的活動數 count = activityService.getCountByGid(id); gameInfo.setCount(count); } catch (TException e) { LOGGER.debug("獲取指定游戲詳情失敗!!", e); return new MessageEntity.Builder(request).msg("跳轉預覽頁面失敗").code(201).success(false) .create(); } map.put("gameInfo",gameInfo); return new MessageEntity.Builder(request).msg("success").code(201).content(map).success(true) .create(); }
@FormToken此標簽:
package com.caobug.client.annotation; import java.lang.annotation.*; /** * TOKEN生成與刪除 * Created by caobug on 14-8-15. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FormToken { /** * 是否在頁面生成TOKEN * * @return */ boolean produce() default false; /** * 是否刪除舊 TOKEN * * @return */ boolean remove() default false; }
實現一個攔截器接口
package com.caobug.client.support.interceptor; import com.caobug.client.annotation.FormToken; import com.caobug.client.support.MessageCode; import com.caobug.client.support.MessageEntity; import com.caobug.client.support.utils.TokenUtils; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.StringUtils; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.lang.reflect.Method; /** * Token 攔截器 * <p/> * Created by caobug on 14-8-15. */ public class FormTokenInterceptor extends HandlerInterceptorAdapter { public final static String TOKEN_NAME = "resubmitToken"; /** * 方法處理前處理 * * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); FormToken formToken = method.getAnnotation(FormToken.class); if (null != formToken) { if ((formToken.produce() && formToken.remove()) || (!formToken.produce() && !formToken.remove())) { throw new RuntimeException("請不要在同一個方法上同時注解:@FormToken(remove = true/false, produce = true/false)"); } else if (formToken.produce()) { request.getSession().setAttribute(TOKEN_NAME, TokenUtils.getToken()); } else if (formToken.remove()) { String serverToken = (String) request.getSession().getAttribute(TOKEN_NAME); String clientToken = request.getParameter(TOKEN_NAME); request.getSession().removeAttribute(TOKEN_NAME); // remove token if (!StringUtils.equals(serverToken, clientToken)) { if (null != method.getAnnotation(ResponseBody.class)) { // JSON response.setContentType(MediaType.APPLICATION_JSON_VALUE); PrintWriter out = response.getWriter(); out.print(new ObjectMapper().writeValueAsString(new MessageEntity.Builder(null). code(MessageCode.SEND_MULTIPLE).msg("無效請求,請刷新頁面后重試").create())); out.flush(); out.close(); } else { // 普通頁面 request.getRequestDispatcher("/error/invalidRequest").forward(request, response); } return false; } } } return super.preHandle(request, response, handler); } }
xml配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="interceptors"> <list> <bean class="com.caobug.client.support.interceptor.FormTokenInterceptor"/> </list> </property> </bean>
2,在提交頁面中接收到這個值:
<input type="hidden" name="token" value="${token}" />
3,提交處理;
@RequestMapping("/SaveDataController/saveData") @ResponseBody @FormToken(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); }
4,第一次提交時,在還沒進入到提交頁面時,就在服務器端生成一個token(攔截器做出此動作),把此token傳遞給提交頁面,點擊“提交”按鈕,進入到處理的method方法,攔截此方法,在攔截器中把session的值清空,對比兩個token,
http://www.cnblogs.com/hdwpdx/archive/2016/03/29/5333943.html