java+react前後端分離項目處理重複提交問題

來源:互聯網
上載者:User

標籤:ble   擴充   package   開發   hold   詳細   factory   err   static   

重複提交的問題在web開發中是很常碰到的一個問題,主要分為前端和後端兩種途徑解決,前端處理一般採用提交事件後,禁止使用者再次點擊提交按鈕,等待服務端結果再重設提交按鈕狀態。

本文著重介紹,通過java後端處理重複提交問題。開發環境是:spring boot 2.0+react+ant+dva,是主要流程思路:

 

以下是詳細步驟代碼:

1:用戶端登陸,服務端登陸成功後返回初始的表單令牌

package com.df.web.manager.security;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.UUID;/** * @類名稱: * @類描述: * @建立人 劉丹 * @建立時間 2018/6/23 * @最後修改人 劉丹. * @最後修改時間 2018/6/23. * @版本:1.0 */public class FormTokenUtil {    public static String refreshFormToken(HttpServletRequest request, HttpServletResponse response) {        String newFormToken = UUID.randomUUID().toString();        response.setHeader("formToken", newFormToken);        request.getSession(true).setAttribute("formToken", newFormToken);        return newFormToken;    }}

2:前端擷取服務端返回的formToken

            sessionStorage.setItem("formToken", resData.result.formToken);

3:在前端統一的request(fetch)的headers中增加表單token項

    return request(serviceUrl,        {            method: "POST",            headers: {                ‘Accept‘: ‘application/json‘,                ‘Content-Type‘: ‘application/json‘,                ‘formToken‘: sessionStorage.getItem("formToken")            },            body: data,            credentials: ‘include‘        });

4:服務端使用aop技術攔截指定註解的Controller請求

package com.df.web.manager.aop;import com.df.web.manager.security.FormTokenUtil;import com.empiresoft.annotation.FormToken;import com.empiresoft.pojo.common.ActionResultGenerator;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * @類名稱: 表單重複提交攔截處理 * @類描述: * @建立人 劉丹 * @建立時間 2018/6/23 * @最後修改人 劉丹. * @最後修改時間 2018/6/23. * @版本:1.0 */@Aspect@Componentpublic class FormTokenAspect {    private final Logger logger = LoggerFactory.getLogger(this.getClass());    /**     * 對formToken註解的Action執行重複提交驗證     *     * @param proceedingJoinPoint     * @param formToken     * @return     */    @Around("@annotation(formToken)")    public Object execute(ProceedingJoinPoint proceedingJoinPoint, FormToken formToken) {        try {            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();            HttpServletRequest request = attributes.getRequest();            HttpServletResponse response = attributes.getResponse();            String strFormToken = request.getHeader("formToken");            if (strFormToken == null) {                return ActionResultGenerator.errorResult("表單Token不可為空!");            }            Object sessionFormToken = request.getSession(true).getAttribute("formToken");            if (sessionFormToken == null || !sessionFormToken.toString().equals(strFormToken)) {                return ActionResultGenerator.errorResult("請勿重複提交資料!");            }            //允許存取            Object o = proceedingJoinPoint.proceed();            //重設表單令牌 且寫入response 重設前端 表單令牌            FormTokenUtil.refreshFormToken(request, response);            return o;        } catch (Throwable e) {            logger.error(e.getMessage());            return ActionResultGenerator.errorResult("發生異常!");        }    }}

5:前端監控Response返回的資料中是否包含表單token項,如果包含則重設前端sessionStorage的表單token。

import fetch from ‘dva/fetch‘;import { message } from ‘antd‘;function parseJSON(response) {  if (response.headers.get("formToken")) {    sessionStorage.setItem("formToken", response.headers.get("formToken"))  }  return response.json();}function checkStatus(response) {  if (response.status >= 200 && response.status < 300) {    return response;  }}/** * Requests a URL, returning a promise. * * @param  {string} url       The URL we want to request * @param  {object} [options] The options we want to pass to "fetch" * @return {object}           An object containing either "data" or "err" */export default function request(url, options) {  return fetch(url, options)    .then(checkStatus)    .then(parseJSON)    .then(data => ({ data }))    .catch((err) => {    });}

 註解定義:

package com.empiresoft.annotation;import java.lang.annotation.*;/** * @類名稱:FormToken註解類 * @類描述:使用此註解 則表示需要驗證FormToken, 用於處理表單重複提交 * @建立人 劉丹 * @建立時間 2018/6/23 * @最後修改人 劉丹. * @最後修改時間 2018/6/23. * @版本:1.0 */@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface FormToken {}

標記需要重複提交驗證

   @FormToken    @RequestMapping(value = "/call_service", method = RequestMethod.POST)    public ActionResult callServiceByPost(@RequestBody CallService callService) throws Exception {        return OauthClientUtil.callUnifiedPlatformService(callService, SecurityUtil.getLoginUser(request), request);    }

 

註:如需允許使用者不同的表單使用不同的表單token,只對同性質表單做重複提交驗證,可在前後端對token名稱"formToken"的命名做擴充處理。

java+react前後端分離項目處理重複提交問題

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.