成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

IE9下的跨域問題小總結(jié)

Jokcy / 525人閱讀

摘要:由于瀏覽器同源策略,凡是發(fā)送請求的協(xié)議域名端口三者之間任意一與當前頁面地址不同即為跨域最近項目要兼容,找了一些資料,實踐了一下,現(xiàn)在總結(jié)一下,避免以后踩坑。解決方案,微軟在和下給我們提供了來進行解決跨域問題,官方的文檔可以在這里看到。

由于瀏覽器同源策略,凡是發(fā)送請求url的協(xié)議、域名、端口三者之間任意一與當前頁面地址不同即為跨域

最近項目要兼容IE9,找了一些資料,實踐了一下,現(xiàn)在總結(jié)一下,避免以后踩坑。

普通請求的跨域 簡單粗暴的解決方案

第一次碰到這個問題,所以就是上網(wǎng)找找有沒有什么好的解決方案。最初找到的方案是這樣的,直接在IE中設(shè)置設(shè)置受信任的站點,然后允許其可以進行跨域訪問,最后在jQuery中設(shè)置開啟跨域請求。oh,No!這么粗暴,好吧,這也是一個不是辦法的辦法,如果做的是一個小項目,用戶不多,那直接寫在用戶手冊里,讓他們自己去配吧。但是,這顯然不是一個好的解決方案啊,那只能繼續(xù)找了。

XDomainRequest(XDR)解決方案

ok,微軟在IE8IE9下給我們提供了XDomainRequest來進行解決跨域問題,官方的文檔可以在 這里看到。當然Github上也有開源的jQuery插件,可以在這里找到。

XDR的限制:

XDR僅支持GETPOST這兩種請求方式,雖然可以使用上面提交的插件來解決前端部分只要進行簡單修改代碼就可以提交PUT/HEAD/DELETE的請求的問題,但是其請求的發(fā)生出去依舊還是將PUT/HEAD/DELETE轉(zhuǎn)化為POST,將HEAD 轉(zhuǎn)化為GET請求。當是POST請求的時候,請求方案會以__method=原請求的方式結(jié)構(gòu)加入到請求體的body中。當是HEAD 請求的時候,請求方案會以__method=原請求的方式結(jié)構(gòu)加入請求url的查詢參數(shù)中?,F(xiàn)在大部分API開發(fā)都是按照RESTful規(guī)范進行設(shè)計的,如果是自己的服務(wù)端還好,可以叫服務(wù)端的同學(xué)添加一個攔截器做一個攔截判斷,然后執(zhí)行對應(yīng)的方法(ps:我想過去應(yīng)該是這個樣子,不知道服務(wù)端的同學(xué)會不會磨刀子)。但是如果你調(diào)用是網(wǎng)上的API的接口的話,那就愛莫能助了。

XDR不支持自定義的請求頭,因此如果你的服務(wù)端是用過header中的自定義參數(shù)進行做身份驗證的話,那也行不通了。

請求頭的Content-Type只允許設(shè)置為text/plain

XDR不允許跨協(xié)議的請求,如果你的網(wǎng)頁是在HTTP協(xié)議下,那么你只能請求HTTP協(xié)議下的接口,不能訪問HTTPS 下的接口。

XDR只接受HTTP/HTTPS 的請求

發(fā)起請求的時候,不會攜帶authentication cookies

JSONP

JSONP的本質(zhì)是動態(tài)的加載

然后自己定義一個上傳的組件,我這里是使用Vue來包裝成一個組件的



這個插件是依賴jQuery的,并且依賴jQuery-UI ,還有要注意的是在IE10以下的版本都要引入jquery.iframe-transport

jquery.xdr-transport

我代碼中發(fā)送數(shù)據(jù)的方式是它在add 方法中返回的data數(shù)據(jù),通過該對象去直接上傳文件,這時上傳的FormData的文件信息中,文件原本是什么類型就是什么類型了,這是我們所期望的。我之前查看官方的文檔,還使用過另一種方式

var jqXHR = $("#fileupload").fileupload("send", {files: filesList})
    .success(function (result, textStatus, jqXHR) {/* ... */})
    .error(function (jqXHR, textStatus, errorThrown) {/* ... */})
    .complete(function (result, textStatus, jqXHR) {/* ... */});

上傳的時候使用的是這樣的方式,發(fā)現(xiàn)FormData中上傳文件的類型變?yōu)榱?b>Content-Type: application/octet-stream,然后服務(wù)器就解析不到數(shù)據(jù)了。所以還是推薦用它原生的submit方式去提交數(shù)據(jù)。

注意

這兩個插件的本質(zhì)還是使用form表單上傳文件,因此我們無法添加自定義的header頭,并且如果原來的服務(wù)器不支持請求重定向的話怎么辦,那就沒有辦法使用jQuery-File-Upload這個插件了。所以最穩(wěn)妥的方式,還是在我們本地做了一層代理,由代理去發(fā)生真正的請求。

下面給出主要的轉(zhuǎn)發(fā)FormDatajava代碼

public ResponseEntity dispatcherUpload(HttpServletRequest request) throws UnsupportedEncodingException {

    String requestUrl = request.getParameter("request_url");
    String redirectUrl = request.getParameter("redirect");
    String fileName = request.getParameter("name");

    if (StringUtils.isEmpty(requestUrl) || StringUtils.isEmpty(redirectUrl))
      throw new BizException(ErrorCode.INVALID_ARGUMENT);

    HttpClient httpClient = new DefaultHttpClient();
    HttpPost httpPost = new HttpPost(requestUrl);
    String auth = request.getParameter("authorization");
    if (!StringUtils.isEmpty(auth))
      httpPost.addHeader("Authorization", request.getParameter("authorization").toString());
    MultipartEntity reqEntity = new MultipartEntity();

    if (!StringUtils.isEmpty(request.getParameter("path"))) {
      StringBody pathBody = new StringBody(request.getParameter("path"));
      reqEntity.addPart("path", pathBody);
    }
    if (!StringUtils.isEmpty(request.getParameter("scope"))) {
      StringBody scopeBody = new StringBody(request.getParameter("scope"));
      reqEntity.addPart("scope", scopeBody);
    }
    if (!StringUtils.isEmpty(request.getParameter("expireDays"))) {
      StringBody expireDaysBody = new StringBody(request.getParameter("expireDays"));
      reqEntity.addPart("expireDays", expireDaysBody);
    }
    if (!StringUtils.isEmpty(fileName)) {
      StringBody nameBody = new StringBody(fileName);
      reqEntity.addPart("name", nameBody);
    }

    MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
    MultiValueMap multiValueMap = multipartHttpServletRequest.getMultiFileMap();
    //todo:現(xiàn)在暫時寫死,不去遍歷map
    if(!(multiValueMap.containsKey(CS_FILE_KEY) || multiValueMap.containsKey(UC_FILE_KEY)))
      throw new BizException(ErrorCode.INVALID_ARGUMENT);
    String fileKey = multiValueMap.containsKey(CS_FILE_KEY) ? CS_FILE_KEY : UC_FILE_KEY;
    MultipartFile multipartFile = multipartHttpServletRequest.getFile(fileKey); // 得到文件數(shù)據(jù)
    if (!multipartFile.isEmpty()) {

      CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartFile;
      DiskFileItem diskFileItem = (DiskFileItem) commonsMultipartFile.getFileItem();
      String filePath = diskFileItem.getStoreLocation().getPath().toString();

      File file = null;
      try {
        //判斷目錄是否已存在,如果filename不為空,將其帶入創(chuàng)建文件(真實還原文件類型,否則是.tmp臨時文件)
        if (StringUtils.isEmpty(fileName)) {
          file = new File(filePath);
        } else {
          file = new File(filePath, fileName);
        }
        if (!file.exists()) {
          file.mkdirs();
        }
        //保存文件
        multipartFile.transferTo(file);
        FileBody bin = new FileBody(file);
        reqEntity.addPart(fileKey, bin);
        httpPost.setEntity(reqEntity);

        HttpHeaders responseHeader = new HttpHeaders();
        HttpResponse httpResponse = null;
        try {
          httpResponse = httpClient.execute(httpPost);
        } catch (Exception e) {
          LOG.error("代理文件上傳失敗,請求地址:{},請求內(nèi)容:{}", requestUrl, null, e);
          JSONObject failedJson = new JSONObject();
          failedJson.put("result", "FAILURE");
          failedJson.put("data", e.toString());
          URI uri = URI.create(redirectUrl + e.toString());
          responseHeader.setLocation(uri);
          return new ResponseEntity(responseHeader, HttpStatus.MOVED_TEMPORARILY);
        }
        LOG.info("狀態(tài)碼:" + httpResponse.getStatusLine().getStatusCode());
        org.apache.http.HttpEntity httpEntity = httpResponse.getEntity();
        //判斷請求是否成功
        String responseBody = "";
        String isSuccess = "SUCCESS";
        if (httpResponse.getStatusLine().getStatusCode() >= HttpStatus.OK.value() && httpResponse.getStatusLine().getStatusCode() < HttpStatus.BAD_REQUEST.value()) {
          if (null != httpEntity) {
//            System.out.println("響應(yīng)內(nèi)容:" + EntityUtils.toString(httpEntity, ContentType.getOrDefault(httpEntity).getCharset()));
            responseBody = EntityUtils.toString(httpEntity, ContentType.getOrDefault(httpEntity).getCharset());
            //處于安全考慮,關(guān)閉數(shù)據(jù)流
            EntityUtils.consume(httpEntity);
          }
        } else {
          //上傳失敗(非2XX)
          isSuccess = "FAILURE";
        }
        JSONObject ResJson = new JSONObject();
        ResJson.put("result", isSuccess);
        ResJson.put("data", responseBody);
        URI uri = URI.create(redirectUrl + URLEncoder.encode(ResJson.toString(), "UTF-8"));
        responseHeader.setLocation(uri);
        return new ResponseEntity(responseHeader, HttpStatus.MOVED_TEMPORARILY);
      } catch (IOException e) {
        throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR, e);
      } finally {
        if (file != null) {
          file.delete();
        }
      }
    }else {
      throw new BizException(HttpStatus.BAD_REQUEST, "PORTAL-APP/INVALID_ARGUMENT", "上傳文件為空");
    }
  }

在轉(zhuǎn)發(fā)文件的時候,我們做了一層轉(zhuǎn)存,原因在于,我們測試一個服務(wù)器的時候,我們直接使用一個緩存的數(shù)據(jù),去寫到FormData中,那邊服務(wù)器接收到的文件對象居然是空的,因此我們才做了一層緩存,用一個真實存在的文件去做。

---end---

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86953.html

相關(guān)文章

  • Vue 兼容 ie9 的全面解決方案

    摘要:本文將針對使用生態(tài)開發(fā)完成的網(wǎng)站,以版本為基礎(chǔ)兼容目標,實現(xiàn)全功能正常使用的全面兼容解決方案。這樣做的目的,是逐步減少全局性方法,使得語言逐步模塊化。此外,使用這個,一旦頁面不處于瀏覽器的當前標簽,就會自動停止刷新。 前言 背景情況 vue - 2.5.11 vue-cli 使用模板 webpack-simple http請求:axios Vue 官方對于 ie 瀏覽器版本兼容情...

    codeKK 評論0 收藏0
  • Web開發(fā)之跨域跨域資源共享

    摘要:例外當涉及到同源策略時,有兩個主要的例外授信范圍兩個相互之間高度互信的域名,如公司域名,不遵守同源策略的限制。端口未將端口號加入到同源策略的組成部分之中,因此和屬于同源并且不受任何限制。 原文鏈接:http://www.devsai.com/2016/11/24/talk-CORS/ 同源策略(same origin policy) 1995年,同源政策由 Netscape 公司引入瀏...

    Eastboat 評論0 收藏0
  • web安全一,同源策略與跨域

    摘要:可以說同源策略在安全中扮演著及其重要的角色。我把這個領(lǐng)域的東西寫成了一個系列,以后還會繼續(xù)完善下去安全一同源策略與跨域安全二攻擊安全三攻擊 之所以要將同源策略與跨域?qū)懺谝黄?,是因為存在瀏覽器的同源策略,才會存在跨域問題 何為同源策略 同源策略是瀏覽器實現(xiàn)的一種安全策略,它限制了不同源之間的文檔和腳本交互的權(quán)限。只有同一個源的腳本才會具有操作dom、讀寫cookie、session 、a...

    cgspine 評論0 收藏0
  • 前端跨域方法論

    摘要:說明是否允許通訊同一域名允許同一域名下的不同文件夾允許不同端口號不允許不同協(xié)議不允許不同域名不允許主域相同,子域不同不允許跨域解決方案由于瀏覽器同源策略是允許標簽這樣的跨域資源嵌套的,所以標簽的資源不受同源策略的限制。 前言 本著學(xué)習(xí)和總結(jié)的態(tài)度寫的技術(shù)輸出,文中有任何錯誤和問題,請大家指出。更多的技術(shù)輸出可以查看我的 github博客。 整理了一些前端的學(xué)習(xí)資源,希望能夠幫助到有需要...

    leejan97 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<