跨域原因産生:在目前域名請求網站中,預設不允許通過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域中存儲的辨別号。
- 存儲Session域中的Token(令牌)與表單送出的Token(令牌)不同。
- 目前使用者的Session中不存在Token(令牌)。
- 使用者送出的表單資料中沒有Token(令牌)。
如何防止别人模拟請求?
使用令牌token解決模拟請求 好處是 唯一性隻能有一次請求
如何拿到如何生成token 改如何防止呢?
使用驗證碼(防止非人工)
轉載于:https://www.cnblogs.com/zhouwen2017/p/10511045.html