跨域

crosDomain.png

服務器端解決,通過一個filter過濾來自移動端服務器的請求,為response添加Access-Control-Allow信息。通過設置Access-Control-Allow-Credentials=true允許客戶端發(fā)送cookie,客戶端需要設置XMLHttpRequest()的withCredentials 屬性為true

 var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;

在ionic中需要設置$http:

  $http({
          method: "GET",
          url: url,
          params: params,
          cache: false,
          timeout: 20000,
          withCredentials:true,
          headers: {'Content-Type': 'application/json;charset=UTF-8','Cache-Control':'no-cache'}
        }).then(function (result) {          
            ...
          }

跨域小知識

客戶端ClientA請求服務器server1,server1的頁面中使用ajax請求了server2中的數(shù)據(jù)就發(fā)生了跨域。默認情況,瀏覽器不允許跨域請求。大致解決思路有:

瀏覽器端解決。

適合開發(fā)者自己調試, 在chrome瀏覽器中添加啟動參數(shù):

--args --disable-web-security --user-data-dir 

server端解決方案JSONP。

通過某些手段規(guī)避瀏覽器的跨域規(guī)則,比如使用JSONP等,JSONP需要客戶端與服務器端配合。
網(wǎng)頁通過動態(tài)插入<script>元素,由它向跨源網(wǎng)址發(fā)出請求,不再受跨域規(guī)則限制。
推薦JQuery,在ajax請求中指定dataType:'jsonp'的方式。這種方式自動實現(xiàn)<script>加回調函數(shù)的效果。
js代碼

<script type="text/javascript" src="jquery.js"></script>  
<script type="text/javascript">  
    $.ajax({  
        url:"http://crossdomain.com/services.php",  
        dataType:'jsonp',  
        data:'',  
        jsonp:'callback',  
        success:function(result) {  
            for(var i in result) {  
                alert(i+":"+result[i]);//循環(huán)輸出a:1,b:2,etc.  
            }  
        },  
        timeout:3000  
    });  
</script>

這種方法需要js實現(xiàn)處理返回結果的回調函數(shù),如果有很多頁面跨域,實現(xiàn)這些回調函數(shù)挺煩人的。
服務器端實現(xiàn),在原來的返回結果基礎上添加回調函數(shù)名稱和括號,默認用success,也可以配合jQuery的ajax請求指定函數(shù)名稱。
支持跨域前的返回:

['data1','data2']

為支持jsonp,修改后的返回:

callbackFunction(['data1','data2'])

server端實現(xiàn)方案2,通過Allow-Control-Access機制。

現(xiàn)代瀏覽器都通過Allow-Control-Access機制允許跨域,原理如下:

  1. 瀏覽器發(fā)現(xiàn)存在跨域請求,不直接拒絕,而是向服務器server2發(fā)多送一個Origin字段把server1的IP地址加端口告知server2,如果是put、delete這種高危請求,瀏覽器先發(fā)送一個options類型的請求。
  2. 如果server2沒有任何允許跨域的意思,瀏覽器不再處理服務器的響應,而是報一個跨域錯誤。
  3. 如果server2允許跨域,需要在response中通知瀏覽器,告知瀏覽器允許誰跨域,允許不允許瀏覽器發(fā)送cookie信息。
  4. 瀏覽器檢查server2返回的信息,如果當前請求合乎規(guī)則,則進一步處理服務器端響應,執(zhí)行js,展示頁面。
    server2允許跨域的java端實現(xiàn),通過filter為response添加Allow-Control-Access信息:
package org.example.core.filter;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jodd.util.StringUtil;

/**
 * @author damowang 20170802 解決移動端開發(fā)瀏覽器跨域問題
 *
 */
public class CORSFilter implements Filter {
    /**客戶端域名,通過init-param配置,在filter初始化時賦值*/
    private String allowOrigin;

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest srequest, ServletResponse sresponse,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) sresponse;
        HttpServletRequest request = (HttpServletRequest) srequest;     
        //設置允許誰(server1的域名或ip)跨域,在一次request中Access-Control-Allow-Methods只能設置一個客戶端地址,因此通過判斷客戶端設置該字段
        if (StringUtil.isNotEmpty(allowOrigin)) {
            List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
            String currentOrigin = request.getHeader("Origin");
            if (allowOriginList.contains(currentOrigin)) {
                response.setHeader("Access-Control-Allow-Origin", currentOrigin);
            }
        }
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
        response.setHeader("Access-Control-Allow-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Cache-Control,Content-Type");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(request, response);

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        allowOrigin = filterConfig.getInitParameter("allowOrigin");

    }
}

web.xml中配置攔截器

<!-- 跨域攔截器 -->
  <filter>
      <filter-name>corsFilter</filter-name>
      <filter-class>org.example.core.filter.CORSFilter</filter-class>
      
      <init-param>
          <param-name>allowOrigin</param-name>
          <param-value>http://server1.com:8100,http://anotherDomainOfServer1.com</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>corsFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>

客戶端允許發(fā)送cookie:

 var xhr = new XMLHttpRequest();
 xhr.withCredentials = true;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容