欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Javascript實(shí)現(xiàn)跨域后臺(tái)設(shè)置攔截的方法詳解

 更新時(shí)間:2017年08月04日 10:45:17   作者:Ryan.Miao  
這篇文章主要給大家介紹了關(guān)于Javascript實(shí)現(xiàn)跨域后臺(tái)設(shè)置攔截的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

本文主要給大家介紹了關(guān)于Javascript跨域后臺(tái)設(shè)置攔截的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。

子域名之間互相訪問(wèn)需要跨域

結(jié)論放在開(kāi)頭:

1.服務(wù)端必須設(shè)置允許跨域

2.客戶端帶cookie需要設(shè)置 withCredentials

3.無(wú)論服務(wù)端是否允許跨域,該request都會(huì)完整執(zhí)行

4. options 預(yù)請(qǐng)求需要設(shè)置返回空,不然requestMapping沒(méi)有支持該方法則出錯(cuò)

環(huán)境搭建

需求

首先需要搭建兩個(gè)環(huán)境。一個(gè)是提供API的server A,一個(gè)是需要跨域訪問(wèn)API的server B。

Server A提供了一個(gè)api。完整的請(qǐng)求request是:

https://local.corstest.com.net:8443/contentmain/getDepositsRoomAndRatePlanInfo.json?htid=759&_=1490855801818

Server B有個(gè)頁(yè)面page:

http://cros.corstest.com.net:3001/test.html

并且這個(gè)page需要請(qǐng)求server A的api。

但由于跨域保護(hù),請(qǐng)求失?。?br />

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'xxxxx' is therefore not allowed access.

修改host

首先本地配置兩個(gè)指向127.0.0.1的host,方便互相跨域。

127.0.0.1 local.corstest.com.net 
127.0.0.1 cros.corstest.com.net

啟動(dòng)項(xiàng)目A,方便提供API。

至于項(xiàng)目B,測(cè)試跨域只要寫(xiě)個(gè)html靜態(tài)頁(yè)面即可。那么就寫(xiě)一個(gè)test.html,并通過(guò)一個(gè)工具發(fā)布:

 browser-sync 

安裝

npm install -g browser-sync

本地啟動(dòng)一個(gè)test.html

browser-sync start --server --files "*.html" --host "cros.corstest.com.net" --port 3001

關(guān)于跨域CORS

ruanyifeng 的文章里說(shuō)瀏覽器將CORS請(qǐng)求分成兩類:簡(jiǎn)單請(qǐng)求(simple request)和非簡(jiǎn)單請(qǐng)求(not-so-simple request)。

其中同時(shí)滿足一下2種標(biāo)準(zhǔn)即為簡(jiǎn)單跨域:

1) 請(qǐng)求方法是以下三種方法之一:

  • HEAD
  • GET
  • POST

2)HTTP的頭信息不超出以下幾種字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三個(gè)值application/x-www-form-urlencoded、multipart/form-data、text/plain

而其他情況,非簡(jiǎn)單請(qǐng)求是那種對(duì)服務(wù)器有特殊要求的請(qǐng)求,比如請(qǐng)求方法是  PUT 或 DELETE ,或者 Content-Type 字段的類型是 application/json 。非簡(jiǎn)單請(qǐng)求的CORS請(qǐng)求,會(huì)在正式通信之前,增加一次HTTP查詢請(qǐng)求,稱為"預(yù)檢"請(qǐng)求(preflight),即 options 請(qǐng)求。

關(guān)鍵

跨域的關(guān)鍵是瀏覽器獲得服務(wù)器的認(rèn)可,而服務(wù)器的認(rèn)可就是header里的 Access-Control-Allow-Origin 。瀏覽器通過(guò)比較服務(wù)端返回的response中是否包含這個(gè)字段,以及包含這個(gè)字段的內(nèi)容是否是當(dāng)前網(wǎng)址來(lái)確定是否跨域。也就是說(shuō)繞過(guò)瀏覽器是可以不用跨域的。

有個(gè)問(wèn)題,看好多文章并沒(méi)有指出。

第一點(diǎn),帶cookie問(wèn)題。瀏覽器設(shè)置 withCredentials 為 true 則會(huì)帶cookie發(fā)送給服務(wù)端。而服務(wù)端設(shè)置 Access-Control-Allow-Credentials 為 true 則接收, false 則不接受。關(guān)鍵是到filter里的時(shí)候才會(huì)決定是否設(shè)置response,那么這時(shí)候cookie已經(jīng)存在request里了吧。(待驗(yàn)證)

驗(yàn)證:server端確實(shí)已經(jīng)接受了cookie,即使設(shè)置為false,服務(wù)端仍舊接受cookie。而客戶端也仍舊可以發(fā)送cookie。

第二點(diǎn),簡(jiǎn)單跨域中,瀏覽器的請(qǐng)求直接發(fā)送給服務(wù)器,服務(wù)器返回是否支持跨域(即是否header加origin), 那么簡(jiǎn)單跨域究竟是請(qǐng)求了服務(wù)端幾次?如果是1次,那么如果服務(wù)端不支持跨域,即沒(méi)有設(shè)置allow,還會(huì)不會(huì)繼續(xù)走下去,會(huì)不會(huì)繼續(xù)request得到結(jié)果后放入response?就是不論跨域不跨域服務(wù)器是否都會(huì)執(zhí)行這個(gè)request對(duì)應(yīng)的計(jì)算。因?yàn)樗械脑O(shè)置header都是給瀏覽器告知的,和服務(wù)端限制無(wú)關(guān)。(待驗(yàn)證)

驗(yàn)證:即使服務(wù)端沒(méi)有設(shè)置允許跨域,當(dāng)客戶端請(qǐng)求過(guò)來(lái)時(shí),服務(wù)端仍舊完整執(zhí)行了請(qǐng)求并返回,只是客戶端沒(méi)有接收。

服務(wù)端需要做點(diǎn)工作

針對(duì)上述兩種跨域。server A需要寫(xiě)一個(gè)filter。

<filter>
 <filter-name>cors</filter-name>
  <filter-class>com.test.filter.CorsFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>cors</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
</filter>

Filter:

public class CorsFilter extends OncePerRequestFilter {

 @Override
 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
   throws ServletException, IOException {
  URL requestURL = new URL(request.getRequestURL().toString());
  String hostName = requestURL.getHost();
  String origin = request.getHeader("Origin");

  int index = hostName.indexOf(".");

  if(index > -1) {
   String domainHost = hostName.substring(index, hostName.length());
   if(!StringUtils.isEmpty(origin) && origin.contains(domainHost)) {
    response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    response.addHeader("Access-Control-Allow-Origin", origin);
    response.addHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.addHeader("Access-Control-Allow-Headers", "Content-Type, Cookie, " +
      "Accept-Encoding, User-Agent, " +
      "Host, Referer, " +
      "X-Requested-With, Accept, " +
      "Accept-Language, Cache-Control, Connection");

    if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
     // CORS "pre-flight" request
     response.setStatus(200);
     return;
    }
   }
  }

  filterChain.doFilter(request, response);
 }
}

上述filter是為了同一個(gè)domain下,不同子域名可以跨域訪問(wèn),而其他domain則不可以,因?yàn)槲覀冃枰蚕韈ookie,所以設(shè)置 Access-Control-Allow-Credentials 為 true . 如果設(shè)置為 false 則不接受cookie。

客戶端,即server B如果想要發(fā)送cookie則需要設(shè)置 withCredentials 為 true .

//原生
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
//jquery
$.ajax({
 ...
 xhrFields: {
  withCredentials: true
 }
 ...
});

注意:針對(duì)非簡(jiǎn)單跨域的時(shí)候發(fā)送 options 請(qǐng)求,服務(wù)端A需要告訴瀏覽器是否支持跨域即可,不要往下走了,不然到指定的requestMapping發(fā)現(xiàn)不支持這個(gè)方法就會(huì)很尷尬了,所以直接返回。

下面針對(duì)簡(jiǎn)單跨域和非簡(jiǎn)單跨域做測(cè)試:

<!DOCTYPE html>
<html lang="en">

 <meta charset="UTF-8">
 <title>test</title>

 <script src="jquery-1.11.3.js"></script>
</head>
<body>

<input type="button" value="GET_Default" onclick="testGetDefault()">
<input type="button" value="GET_JSON" onclick="testGetJSON()">
<input type="button" value="POST_Default" onclick="testPostDefault()">
<input type="button" value="POST_JSON" onclick="testPostJson()">
<input type="button" value="PUT" onclick="testPUT()">

<script>
 var getUrl = "https://local.corstest.com.net:8443/contentmain/getDepositsRoomAndRatePlanInfo.json?htid=759";
 var postUrl = "https://local.corstest.com.net:8443/contentmain/saveReservationDeposits.json?htid=759";

 function testGetDefault(){
  sendAjax("GET",getUrl, "json", "application/x-www-form-urlencoded");
 }
 function testGetJSON(){
  sendAjax("GET",getUrl, "json", "application/json; charset=utf-8");
 }
 function testPostDefault(){
  sendAjax("POST",postUrl, "json", "application/x-www-form-urlencoded");
 }

 function testPostJson(){
  sendAjax("POST",postUrl, "json", "application/json; charset=utf-8");
 }

 function testPUT(){
  sendAjax("PUT",postUrl, "json", "application/json; charset=utf-8");
 }

 
 function sendAjax(type, url, dataType, contentType){
  $.ajax( { 
   type: type,
   url: url,
   xhrFields: {
    withCredentials: true
   },
   dataType : dataType, // accept type
   contentType: contentType, //request type, default is application/x-www-form-urlencoded
   success: function(result){
    console.log(result);
   },
   error: function (xhr) {
    console.log(xhr);
   }
  });
 }


</script>
</body>
</html>

結(jié)果:

GET default:

只發(fā)送一個(gè)正常的get請(qǐng)求。

GET json:

先發(fā)送一個(gè)options如下:

General:
Request URL:https://local.corstest.com.net:8443/contentmain/getDepositsRoomAndRatePlanInfo.json?htid=759
Request Method:OPTIONS
Status Code:200 OK
Remote Address:127.0.0.1:8443

Response Headers:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, Cookie, Accept-Encoding, User-Agent, Host, Referer, X-Requested-With, Accept, Accept-Language, Cache-Control, Connection
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:http://cros.corstest.com.net:3001
Content-Length:0
Date:Thu, 30 Mar 2017 12:47:44 GMT
Server:Apache-Coyote/1.1

Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:GET
Connection:keep-alive
Host:local.corstest.com.net:8443
Origin:http://cros.corstest.com.net:3001
Referer:http://cros.corstest.com.net:3001/test.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

然后再發(fā)送正常的Get請(qǐng)求。

post default:

正常發(fā)送請(qǐng)求。

post json: 先發(fā)送一個(gè)options請(qǐng)求。然后再發(fā)送正常的請(qǐng)求。

其他同理,總之,非簡(jiǎn)單跨域會(huì)多發(fā)一次options請(qǐng)求來(lái)確認(rèn)是否支持跨域,這時(shí)候服務(wù)端一定要返回支持跨域,并且直接返回即可。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論