1. 程式人生 > >spring防止F5重新整理提交重複表單,為form加入引數token

spring防止F5重新整理提交重複表單,為form加入引數token

直接上程式碼.

建立一個類:Form:

package form;

import java.io.Serializable;
import java.util.Date;


import org.apache.commons.lang.builder.ToStringBuilder;
/**
* 表單類
*
* @author DigitalSonic
*/
public class Form implements Serializable {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 8796758608626021150L;
public static final String FORM_UNIQ_ID_FIELD_NAME = "_form_uniq_id";
/** 表單標識*/
private String token;
/** 表單建立時間*/
private Date createTime;
/**
* 建構函式
*/
public Form(String token) {
this.token = token;
this.createTime = new Date();
}
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
public String getToken() {
return token;
}
public Date getCreateTime() {
return createTime;
}

}

建立一個介面:

package form;
import javax.servlet.http.HttpServletRequest;


import org.aioframework.web.form.entity.Form;
/**
* 表單管理器,負責管理Session中的表單。
*
* @author DigitalSonic
*/


public interface FormManager {
/**
* 生成一個新的表單
*/
public Form newForm(HttpServletRequest request);
/**
* 判斷表單是否存在。
*/
public boolean hasForm(HttpServletRequest request, String token);
/**
* 訪問引數中是否存在表單Token。
*/
public boolean hasFormToken(HttpServletRequest request);
/**
* 銷燬一個表單
*/
public void destroyToken(HttpServletRequest request, String token);
/**
* 打印表單資訊。
*/
public String dumpForm(HttpServletRequest request, String token);
}

建立類FormManager Impl實現自定義介面FormManager :

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;


import org.aioframework.web.form.entity.Form;
import org.aioframework.web.form.service.FormManager;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 表單管理器實現類
*
* @author DigitalSonic
*/
@Service("formManager")
@Transactional
public class FormManagerImpl implements FormManager {
private static final String SESSION_KEY_OF_FROMS = "_forms_in_session";
/** 表單最大個數 */
private int maxFormNum = 7;

/**
* 銷燬一個表單
*/
public void destroyToken(HttpServletRequest request, String token) {
getForms(request).remove(token);
}
/**
* 打印表單資訊。
*/
public String dumpForm(HttpServletRequest request, String token) {
Form form = getForms(request).get(token);
if (form == null) {
return "null";
}
return form.toString();
}
/**
* 判斷表單是否存在。如果token為null,直接返回false。
*
* @see #getForms(HttpServletRequest)
*/
public boolean hasForm(HttpServletRequest request, String token) {
if (token == null) {
return false;
}
return getForms(request).containsKey(token);
}

/**
* 訪問引數中是否存在表單Token。
*/
public boolean hasFormToken(HttpServletRequest request) {
String formToken = request.getParameter(Form.FORM_UNIQ_ID_FIELD_NAME);
return StringUtils.isNotBlank(formToken);
}
/**
* 生成一個新的表單,如果目前表單個數大於設定的最大表單數則先刪除最早的一個表單。<br>
* 新表單用RandomStringUtils.randomAlphanumeric(32)生成Token。
*
* @return 建立的新表單
* @see #removeOldestForm(HttpServletRequest)
* @see org.apache.commons.lang.RandomStringUtils#random(int)
*/
public Form newForm(HttpServletRequest request) {
Form form = new Form(RandomStringUtils.randomAlphanumeric(32));
Map<String, Form> forms = getForms(request);
synchronized (forms) {
// 如果目前表單個數大於等於最大表單數,那麼刪除最老的表單,新增新表單。
if (forms.size() >= maxFormNum) {
removeOldestForm(request);
}
forms.put(form.getToken(), form);
}
return form;
}
/**
* 獲得目前session中的表單列表。
*
* @return 返回的Map中以表單的token為鍵,Form物件為值
*/
@SuppressWarnings("unchecked")
protected Map<String, Form> getForms(HttpServletRequest request) {
Map<String, Form> formsInSession = null;
HttpSession session = request.getSession();
synchronized (session) {
formsInSession = (Map<String, Form>) session.getAttribute(SESSION_KEY_OF_FROMS);
if (formsInSession == null) {
formsInSession = new HashMap<String, Form>();
session.setAttribute(SESSION_KEY_OF_FROMS, formsInSession);
}
}
return formsInSession;
}
/**
* 刪除最老的Form
*
* @see #destroyToken(HttpServletRequest, String)
*/
protected void removeOldestForm(HttpServletRequest request) {
List<Form> forms = new ArrayList<Form>(getForms(request).values());
if (!forms.isEmpty()) {
Form oldestForm = forms.get(0);
for (Form form : forms) {
if (form.getCreateTime().before(oldestForm.getCreateTime())) {
oldestForm = form;
}
}
destroyToken(request, oldestForm.getToken());
}
}
public void setMaxFormNum(int maxFormNum) {
this.maxFormNum = maxFormNum;
}
}

sping配置檔案增加:

<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="form.EncodingInterceptor" />
</mvc:interceptor>

</mvc:interceptors>

EncodingInterceptor為自定義的類,程式碼如下:

package form;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.aioframework.web.form.entity.Form;
import org.aioframework.web.form.service.FormManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;


/**
* 字符集攔截器
*
*/
public class EncodingInterceptor implements HandlerInterceptor {
@Autowired
private FormManager formManager;
/**
* 在controller後攔截
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) throws Exception {


}


public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView modelAndView) throws Exception {


}


/**
* 在controller前攔截
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
boolean flag = true;
String token = request.getParameter(Form.FORM_UNIQ_ID_FIELD_NAME);
if (token != null && !"".equals(token)) {
if (formManager.hasForm(request, token)) {
formManager.destroyToken(request, token);
} else {
flag = false;
throw new Exception("表單重複提交或過期,令牌[" + token + "]");
}
}
return flag;
}
}

使用發放:

到表單頁面的方法中增加程式碼:

Form from = formManager.newForm(request);
request.setAttribute("token", from.getToken());

頁面中的form表單中增加一個input:

<input type="hidden" value="${token }" name="_form_uniq_id" />

複製粘貼後修改下包名可以直接使用。

相關推薦

spring防止F5重新整理提交重複form加入引數token

直接上程式碼. 建立一個類:Form: package form; import java.io.Serializable; import java.util.Date; import org.apache.commons.lang.builder.ToStringBuil

防止重新整理頁面造成重複提交

  public partial class _Default : System.Web.UI.Page {     protected void Page_Load(object sender, EventArgs e)     {         //第一次載入的時候,

SpringBoot防止重複請求重複提交超級簡單的註解實現之四(終極版)

前言:上篇文章有的童鞋說不行啊,怎麼不能防止重複提交呢! 首先需要說明的是之前的防止重複提交是指:一次請求完成之前防止重複提交,當然擴充套件下就可以做到會話間防止重複提交,還可以擴充套件為某個時間段或者永久防止重複提交(這個我就不實現了),下面我來擴充套件一下相同會話防止重

SpringBoot防止重複請求重複提交超級簡單的註解實現之三(升級版2)

升級攔截器上一篇文章留下2個問題1.某些情況下request獲取不到,或造成異常情況,為了處理這種情況我將獲取Request的方法進行了升級2.能不能在異常發生的時候就將重複提交標記就移除呢?當然可以!通過@AfterThrowing即可實現下面是改造後的攔截器程式碼:/**

Java防止非法和重複提交的分析

第一,對於不支援POST的,可以簡單的使用如下程式碼 if ("POST".equals(request.getMethod())) {  // 正常進行}else{  // 異常請求  out.print("異常訪問");  return;} 如果是servlet, 可以

dwz問題之頁面提交僅區域性重新整理table表格

一、問題 後臺管理系統有一個頁面,點選提交按鈕提交表單時,頁面整體都重新整理了。 原則上是提交表單後,表單資訊儲存原來的,只重新整理表格。 二、經過 接下來為了解決問題,開始找dwz框架裡面區域性重新整理的功能。 一種是API呼叫方式: $('#xxID').lo

使用ajax提交form包括ajax文件上傳 轉http://www.cnblogs.com/zhuxiaojie/p/4783939.html

ima option img jquery選擇器 open request resp logs ges 使用ajax提交form表單,包括ajax文件上傳 前言 使用ajax請求數據,很多人都會,比如說: $.post(path,{data:data},function

服務端Json數據+js單數據提交交互插件(base-form.js)

json 舉例 () 編輯 表單 服務器 erro 問題 java 我們在做表單的查看、編輯裏涉及兩個點: 點1,提交Form表單到服務器,保存到數據庫 點2,頁面顯示Form表單裏的所有字段 如果表單的字段很多,這兩個點會有兩個問題: 1,提交Form時,如何少量代碼

學習日記13、ajax同時提交from和多個參數

表單 reload log DC change AD UC sca col if ($("form").valid()) { $.ajax({ url: "@Url.Action("EditCusAndCusCard")"

使用ajax提交form包括ajax文件上傳

開發者 使用 sub 決定 發現 cli 也會 pos pre 前言使用ajax請求數據,很多人都會,比如說:$.post(path,{data:data},function(data){ ...},"json");又或者是這樣的ajax$.ajax({

php對前臺提交資料做安全處理(防SQL注入和XSS攻擊等)

/** * 防sql注入字串轉義 * @param $content 要轉義內容 * @return array|string */ public static function escapeString($content) { $pa

一個按鈕提交兩個form分別提交到兩個action裡第一個form的資料丟失

--背景 在一個iframe開啟的窗口裡,有兩個需要提交的form,而且需要提交到不同的兩個action裡,正常操作下丟失第一個form的資料 --解決方法 在這兩個form下新增一個新的iframe標籤<iframe id = "這個id要與這個視窗的iframe的id不同"&g

ajax提交formH5的required屬性沒起作用

1、 ajax提交form表單,required屬性不起作用 錯誤程式碼如下 <form id="order"> <input type="text" name="name" required /> <input type="submit

php將使用者資訊提交並且以txt文件打印出來

1、分析:     ====不推薦這種======== <?php function foo(){ // global $message; if(empty($_POST['username'])){ echo "要先輸入名

使用FromData提交包括檔案上傳

一、概述 FromData物件的使用: 用一些鍵值對來模擬一系列表單控制元件:即把form中所有的元素的name與value組成一個queryString。 非同步上傳二進位制檔案。 二、使用 1、建立一個空物件例項 var myform = new

前臺使用資料庫model和Html.BeginForm("action", "controller", FormMethod.Post)提交在儲存到資料庫前對錶單項進行判斷的方法(一)

前端: @model DBEF.XXX  @using (Html.BeginForm("action", "controller", FormMethod.Post))     {         @Html.Valid

PHP提交提交到其它頁面和提交到本身

二種提交方式,提交到其它頁面和提交到本身見程式碼: <!DOCTYPE html> <html> <title>表單提交開始</title>       &nb

Spring MVC 資料繫結和標籤庫

資料繫結是將使用者輸入繫結到領域模型的一種特性。 資料繫結的好處: 1. 型別總是為 String 的 HTTP 請求引數,可用於填充不同型別的物件屬性。 2. 當輸入驗證失敗時,會重新生成一個 HTML 表單。 為了高效的使用資料繫結,還需要 Spring 的表單標籤庫。表單標籤庫中包含了可以用在

使用httpClient模擬提交部件

使用httpClient模擬提交多表單部件 在pom.xml加入對httpclient的必需的jar包的依賴<dependency> <groupId>org.apache.httpcomponents</groupId> <ar

cocos creator 提交from定向支付寶

      接到個需求,遊戲中支付要向一個地址提交一個表單,然後那個地址會重新定向到一個網頁,網頁會喚醒支付寶這些。有點不好說,大概就是遊戲中提交到後臺寫的web頁面,web頁面會通過你傳過來引數會喚醒支付寶支付。大概就是這麼回事。開始的想法是用webView載入一個轉成字串