跨域總結(整理)

跨域javascript

1、跨域是什麼?爲何會存在跨域?前端

  ①、廣義的定義:一個域下的文檔或腳本試圖去請求另外一個域下的資源,如:www.baidu.com去請求www.google.com下的資源;vue

      如相似:資源跳轉(<a>標籤連接、重定向、表單提交)、資源嵌入(<link>、<script>、<img>、<frame>等DOM標籤)、腳本請求(JS發起的Ajax請求等)java

    狹義的定義:由瀏覽器同源策略限制的一類請求場景,這也是咱們一般說的跨域問題node

  ②、由於瀏覽器的「同源策略nginx

    ①、什麼是同源策略?爲何要有同源策略?ajax

      a、同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,若是缺乏了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。spring

         所謂同源是指"協議+域名+端口"三者相同,即使兩個不一樣的域名指向同一個ip地址,也非同源。json

      b、瀏覽器施加的安全限制後端

2、跨域的解決方式?

  一、 經過jsonp跨域
  二、 document.domain + iframe跨域
  三、 location.hash + iframe
  四、 window.name + iframe跨域
  五、 postMessage跨域
  六、 跨域資源共享(CORS)
  七、 nginx代理跨域
  八、 nodejs中間件代理跨域
  九、 WebSocket協議跨域

  此處就介紹一下:JSONP 跟 CORS 這兩種方式

  ①、JSONP

    擴展:JSONP 全稱是JSON with Padding,是爲了解決跨域請求資源而產生的解決方案,是一種依靠開發人員創造出的一種非官方跨域數據交互協議。

    JSON是描述信息的格式,JSONP是信息傳遞雙方約定的方法。

    前端代碼:

    a、原生方式:

      <script type="text/javascript" src="http://localhost:8080/api/test?callback=test"></script>
      <script type="text/javascript">
        function test(arg){
         //.....
        }
      </script>

     服務端返回以下(返回時即執行全局函數):test({"status": true, "user": "admin"})

    b、query ajax:
      $.ajax({       url: 'http://localhost.com:8080/login',       type: 'get',       dataType: 'jsonp', // 請求方式爲jsonp       jsonpCallback: "test", // 自定義回調函數名       data: {}       });

     c、vue.js:

        this.$http.jsonp('http://www.domain2.com:8080/login',

                    { params: {}, jsonp: 'test' }

                  ).then((res) => { console.log(res); })

    後端代碼:

       
        String data = new Gson().toJson(...);
        PrintWriter out = response.getWriter();
        out.write(callback + "(" + data + ")");    Java後端實現:        
        String callback = request.getParameter("callback");
    Node.js後端實現:
      var querystring = require('querystring');       
var http = require('http');       var server = http.createServer();       server.on('request', function(req, res) {       var params = qs.parse(req.url.split('?')[1]);         var fn = params.callback;         // jsonp返回設置         res.writeHead(200, { 'Content-Type': 'text/javascript' });         res.write(fn + '(' + JSON.stringify(params) + ')');         res.end();       });       server.listen('8080');       console.log('Server is running at port 8080...');
  ②、CORS
    普通跨域請求:只服務端設置Access-Control-Allow-Origin便可,前端無須設置。
    帶cookie請求:先後端都須要設置字段,另外需注意:所帶cookie爲跨域請求接口所在域的cookie,而非當前頁。
    目前,全部瀏覽器都支持該功能(IE8+:IE8/9須要使用XDomainRequest對象來支持CORS)),CORS也已經成爲主流的跨域解決方案。

    前端代碼:
      a、原生ajax
          // 前端設置是否帶cookie
          xhr.withCredentials = true;
        示例代碼:
          var xhr = new XMLHttpRequest();  // IE8/9需用window.XDomainRequest兼容
          // 前端設置是否帶cookie
          xhr.withCredentials = true;
          xhr.open('post', 'http://www.domain2.com:8080/login', true);
          xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
          xhr.send('user=admin');
          xhr.onreadystatechange = function() {
            if (xhr.readyState == 4 && xhr.status == 200) {
              alert(xhr.responseText);
            }
          };
      b、JQuery ajax
        $.ajax({
          ...
          xhrFields: {
            withCredentials: true // 前端設置是否帶cookie
          },
          crossDomain: true, // 會讓請求頭中包含跨域的額外信息,但不會含cookie
          ...
        });

      c、VUE
        框架在vue-resource封裝的ajax組件中加入如下代碼:
        Vue.http.options.credentials = true

    服務端設置:
      若後端設置成功,前端瀏覽器控制檯則不會出現跨域報錯信息,反之,說明沒設成功。
      
a、Java後臺:
        
response.setHeader("Access-Control-Allow-Origin", "http://localhost.com"); // 如有端口需寫全(協議+域名+端口)
        response.setHeader("Access-Control-Allow-Credentials", "true");
      
b、Nodejs後臺示例:
       
 var http = require('http');
        var server = http.createServer();
        var qs = require('querystring');
        server.on('request', function(req, res) {
          var postData = '';
          // 數據塊接收中
          req.addListener('data', function(chunk) {
            postData += chunk;
          });
          // 數據接收完畢
          req.addListener('end', function() {
            postData = qs.parse(postData);
            // 跨域後臺設置
            res.writeHead(200, {
              'Access-Control-Allow-Credentials': 'true',    // 後端容許發送Cookie
              'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 容許訪問的域(協議+域名+端口)
              'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'    // HttpOnly:腳本沒法讀取cookie
            });
            res.write(JSON.stringify(postData));
            res.end();
          });
        });
        server.listen('8080');
        console.log('Server is running at port 8080...');

    CORS高級應用:

  springmvc4.2版本增長了對cors的支持。

  目前我所作的項目基本都是springboot進行開發,因此我這裏貼下在springboot中的使用。

複製代碼
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter{

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
複製代碼

  能夠在addMapping中配置咱們的路徑。/**表明全部路徑。

  固然也能夠修改其它屬性

複製代碼
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter{

    @Override
    public void addCorsMappings(CorsRegistry registry) {
           registry.addMapping("/api/**")
           .allowedOrigins("http://192.168.1.97")
           .allowedMethods("GET", "POST")
           .allowCredentials(false).maxAge(3600);
    }
複製代碼

  以上兩種,都是針對全局配置,若是你想作到更細緻也可使用@CrossOrigin這個註解在controller類中使用。

@CrossOrigin(origins = "http://192.168.1.97:8080", maxAge = 3600)
@RequestMapping("rest_index")
@RestController
public class IndexController{

  這樣就能夠指定該controller中全部方法都能處理來自http:19.168.1.97:8080中的請求。

相關文章
相關標籤/搜索