天天看點

跨域解決方案以及重複送出解決方案表單重複送出解決方案(防止Http重複送出)

跨域原因産生:在目前域名請求網站中,預設不允許通過ajax請求發送其他域名

解決方案

使用背景response添加header

背景response添加header,response.setHeader("Access-Control-Allow-Origin", "*"); 支援所有網站

使用JSONP

$.ajax({

            type : "POST",

            async : false,

            url : "http://a.a.com/a/FromUserServlet?userName=張三",

            dataType : "jsonp",//資料類型為jsonp 

            jsonp : "jsonpCallback",//服務端用于接收callback調用的function名的參數 

            success : function(data) {

                alert(data.result);

            },

            error : function() {

                alert('fail');

            }

        });

jquery 中jsonp的實作原理

  

在同源政策下,在某個伺服器下的頁面是無法擷取到該伺服器以外的資料的,即一般的ajax是不能進行跨域請求的。但 img、iframe 、script等标簽是個例外,這些标簽可以通過src屬性請求到其他伺服器上的資料。利用 script标簽的開放政策,我們可以實作跨域請求資料,當然這需要伺服器端的配合。 Jquery中ajax 的核心是通過 XmlHttpRequest擷取非本頁内容,而jsonp的核心則是動态添加 <script>标簽來調用伺服器提供的 js腳本。

  當我們正常地請求一個JSON資料的時候,服務端傳回的是一串 JSON類型的資料,而我們使用 JSONP模式來請求資料的時候服務端傳回的是一段可執行的 JavaScript代碼。因為jsonp 跨域的原理就是用的動态加載 script的src ,是以我們隻能把參數通過 url的方式傳遞,是以jsonp的 type類型隻能是get !

示例:

$.ajax({

    url: 'http://192.168.1.114/yii/demos/test.php', //不同的域

    type: 'GET', // jsonp模式隻有GET 是合法的

    data: {

        'action': 'aaron'

    },

    dataType: 'jsonp', // 資料類型

    jsonp: 'backfunc', // 指定回調函數名,與伺服器端接收的一緻,并回傳回來

})

其實jquery 内部會轉化成

http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron

然後動态加載

<script type="text/javascript"src="http://192.168.1.114/yii/demos/test.php?backfunc= jQuery2030038573939353227615_1402643146875&action=aaron"></script>

然後後端就會執行backfunc(傳遞參數 ),把資料通過實參的形式發送出去。

  使用JSONP 模式來請求資料的整個流程:用戶端發送一個請求,規定一個可執行的函數名(這裡就是 jQuery做了封裝的處理,自動幫你生成回調函數并把資料取出來供success屬性方法來調用,而不是傳遞的一個回調句柄),伺服器端接受了這個 backfunc函數名,然後把資料通過實參的形式發送出去

(在jquery 源碼中, jsonp的實作方式是動态添加<script>标簽來調用伺服器提供的 js腳本。jquery 會在window對象中加載一個全局的函數,當 <script>代碼插入時函數執行,執行完畢後就 <script>會被移除。同時jquery還對非跨域的請求進行了優化,如果這個請求是在同一個域名下那麼他就會像正常的 Ajax請求一樣工作。)

後端代碼:

  

@WebServlet("/FromUserServlet")

publicclass FromUserServlet extends HttpServlet {

    @Override

    protectedvoid doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        doPost(req, resp);

    }

    @Override

    protectedvoid doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setCharacterEncoding("UTF-8");

        // resp.setHeader("Access-Control-Allow-Origin", "*");

         String userName = req.getParameter("userName");

         String userAge = req.getParameter("userAge");

         System.out.println(userName + "----" + userAge+"---"+req.getMethod());

        // JSONObject JSONObject1 = new JSONObject();

        // JSONObject1.put("success", "添加成功!");

        // resp.getWriter().write("callbackparam(" + JSONObject1.toJSONString()

        // + ")");

        try {

            resp.setContentType("text/plain");

            resp.setHeader("Pragma", "No-cache");

            resp.setHeader("Cache-Control", "no-cache");

            resp.setDateHeader("Expires", 0);

            PrintWriter out = resp.getWriter();

            JSONObject resultJSON = new JSONObject(); // 根據需要拼裝json

            resultJSON.put("result", "content");

            String jsonpCallback = req.getParameter("jsonpCallback");// 用戶端請求參數

            out.println(jsonpCallback + "(" + resultJSON.toJSONString() + ")");// 傳回jsonp格式資料

            out.flush();

            out.close();

        } catch (Exception e) {

            // TODO: handle exception

        }

    }

}

JSONP的優缺點:

JSONP隻支援get請求不支援psot請求

背景Http請求轉發

  使用HttpClinet轉發進行轉發 

使用接口網關

使用nginx轉發。

使用SpringCloud網關

表單重複送出解決方案(防止Http重複送出)

發生場景

網絡延時

 在平時開發中,如果網速比較慢的情況下,使用者送出表單後,發現伺服器半天都沒有響應,那麼使用者可能會以為是自己沒有送出表單,就會再點選送出按鈕重複送出表單,我們在開發中必須防止表單重複送出。

重新重新整理

表單送出後使用者點選【重新整理】按鈕導緻表單重複送出

點選浏覽器的【後退】按鈕回退到表單頁面後進行再次送出

使用者送出表單後,點選浏覽器的【後退】按鈕回退到表單頁面後進行再次送出

解決方案

使用javascript 解決

 既然存在上述所說的表單重複送出問題,那麼我們就要想辦法解決,比較常用的方法是采用JavaScript來防止表單重複送出,

除了用這種方式之外,經常見的另一種方式就是表單送出之後,将送出按鈕設定為不可用,讓使用者沒有機會點選第二次送出按鈕

使用後端送出解決

    在伺服器端生成一個唯一的随機辨別号,專業術語稱為Token(令牌),同時在目前使用者的Session域中儲存這個Token。然後将Token發送到用戶端的Form表單中,在Form表單中使用隐藏域來存儲這個Token,表單送出的時候連同這個Token一起送出到伺服器端,然後在伺服器端判斷用戶端送出上來的Token與伺服器端生成的Token是否一緻,如果不一緻,那就是重複送出了,此時伺服器端就可以不處理重複送出的表單。如果相同則處理表單送出,處理完後清除目前使用者的Session域中存儲的辨別号。

  1. 存儲Session域中的Token(令牌)與表單送出的Token(令牌)不同。
  2. 目前使用者的Session中不存在Token(令牌)。
  3. 使用者送出的表單資料中沒有Token(令牌)。

如何防止别人模拟請求?

使用令牌token解決模拟請求  好處是 唯一性隻能有一次請求

如何拿到如何生成token  改如何防止呢?

使用驗證碼(防止非人工)

轉載于:https://www.cnblogs.com/zhouwen2017/p/10511045.html

繼續閱讀