• 【JS】AJAX跨域-JSONP解决方案(一)


    AJAX跨域介绍

      AJAX 跨域访问是用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面

      由于安全方面的原因, 客户端js使用xmlhttprequest只能用来向来源网站发送请求,比如在www.readlog.cn下去请求test.readlog.cn的数据,都是不行的。

      什么是AJAX跨域问题

    • 简单来说,就是前端调用后端服务接口时
    • 如果服务接口不是同一个域,就会产生跨域问题

      AJAX跨域场景

    • 前后端分离、服务化的开发模式
    • 前后端开发独立,前端需要大量调用后端接口的场景
    • 只要后端接口不是同一个域,就会产生跨域问题
    • 跨域问题很普遍,解决跨域问题也很重要

      AJAX跨域原因

    • 浏览器限制:浏览器安全校验限制
    • 跨域(协议、域名、端口任何一个不一样都会认为是跨域)
    • XHR(XMLHttpRequest)请求

      AJAX跨域问题解决思路

    • 浏览器:浏览器取下跨域校验,实际价值不大
    • XHR:不使用XHR,使用JSONP,有很多弊端,无法满足现在的开发要求
    • 跨域:被调用方修改支持跨域调用(指定参数);调用方修改隐藏跨域(基于代理)

      如图:

        

    解决跨域问题

      实例

        1、新建一个SpringMVC的Maven工程,参考:【Maven】Eclipse 使用Maven创建SpringMVC Web项目,pom.xml文件如下:

      1 <project xmlns="http://maven.apache.org/POM/4.0.0"
      2     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      4     <modelVersion>4.0.0</modelVersion>
      5     <groupId>com.test</groupId>
      6     <artifactId>test-ajax-cross</artifactId>
      7     <packaging>war</packaging>
      8     <version>0.0.1-SNAPSHOT</version>
      9     <!-- 定义maven变量 -->
     10     <properties>
     11         <!-- spring -->
     12         <spring.version>4.2.0.RELEASE</spring.version>
     13 
     14         <!-- log -->
     15         <commons-logging.version>1.1.3</commons-logging.version>
     16 
     17         <!-- Servlet -->
     18         <servlet.version>3.0.1</servlet.version>
     19         <jsp-api.version>2.2</jsp-api.version>
     20 
     21         <!-- jstl -->
     22         <jstl.version>1.2</jstl.version>
     23         <standard.version>1.1.2</standard.version>
     24 
     25         <!-- Tool -->
     26         <!-- jackson json包 -->
     27         <jackson-databind.version>2.9.7</jackson-databind.version>
     28         <jackson-core.version>2.9.7</jackson-core.version>
     29         <jackson-annotations.version>2.9.7</jackson-annotations.version>
     30 
     31         <!-- test -->
     32         <junit.version>3.8.1</junit.version>
     33 
     34         <!-- jdk -->
     35         <jdk.version>1.8</jdk.version>
     36         <maven.compiler.plugin.version>2.3.2</maven.compiler.plugin.version>
     37     </properties>
     38 
     39 
     40     <dependencies>
     41 
     42         <dependency>
     43             <groupId>org.springframework</groupId>
     44             <artifactId>spring-core</artifactId>
     45             <version>${spring.version}</version>
     46         </dependency>
     47 
     48         <dependency>
     49             <groupId>org.springframework</groupId>
     50             <artifactId>spring-beans</artifactId>
     51             <version>${spring.version}</version>
     52         </dependency>
     53 
     54         <dependency>
     55             <groupId>org.springframework</groupId>
     56             <artifactId>spring-context</artifactId>
     57             <version>${spring.version}</version>
     58         </dependency>
     59 
     60         <dependency>
     61             <groupId>org.springframework</groupId>
     62             <artifactId>spring-jdbc</artifactId>
     63             <version>${spring.version}</version>
     64         </dependency>
     65 
     66 
     67         <dependency>
     68             <groupId>org.springframework</groupId>
     69             <artifactId>spring-expression</artifactId>
     70             <version>${spring.version}</version>
     71         </dependency>
     72 
     73         <dependency>
     74             <groupId>org.springframework</groupId>
     75             <artifactId>spring-web</artifactId>
     76             <version>${spring.version}</version>
     77         </dependency>
     78 
     79         <dependency>
     80             <groupId>org.springframework</groupId>
     81             <artifactId>spring-webmvc</artifactId>
     82             <version>${spring.version}</version>
     83         </dependency>
     84 
     85         <dependency>
     86             <groupId>org.springframework</groupId>
     87             <artifactId>spring-tx</artifactId>
     88             <version>${spring.version}</version>
     89         </dependency>
     90 
     91 
     92 
     93 
     94         <!-- Servlet -->
     95         <dependency>
     96             <groupId>javax.servlet</groupId>
     97             <artifactId>javax.servlet-api</artifactId>
     98             <version>${servlet.version}</version>
     99             <scope>provided</scope>
    100         </dependency>
    101         <dependency>
    102             <groupId>javax.servlet.jsp</groupId>
    103             <artifactId>jsp-api</artifactId>
    104             <version>${jsp-api.version}</version>
    105             <scope>provided</scope>
    106         </dependency>
    107 
    108         <!-- jstl -->
    109         <dependency>
    110             <groupId>javax.servlet</groupId>
    111             <artifactId>jstl</artifactId>
    112             <version>${jstl.version}</version>
    113         </dependency>
    114 
    115         <dependency>
    116             <groupId>taglibs</groupId>
    117             <artifactId>standard</artifactId>
    118             <version>${standard.version}</version>
    119         </dependency>
    120 
    121 
    122         <!-- jackson json包 -->
    123         <dependency>
    124             <groupId>com.fasterxml.jackson.core</groupId>
    125             <artifactId>jackson-databind</artifactId>
    126             <version>${jackson-databind.version}</version>
    127         </dependency>
    128 
    129         <dependency>
    130             <groupId>com.fasterxml.jackson.core</groupId>
    131             <artifactId>jackson-core</artifactId>
    132             <version>${jackson-core.version}</version>
    133         </dependency>
    134 
    135         <dependency>
    136             <groupId>com.fasterxml.jackson.core</groupId>
    137             <artifactId>jackson-annotations</artifactId>
    138             <version>${jackson-annotations.version}</version>
    139         </dependency>
    140 
    141         <!-- test -->
    142         <dependency>
    143             <groupId>junit</groupId>
    144             <artifactId>junit</artifactId>
    145             <version>${junit.version}</version>
    146             <scope>test</scope>
    147         </dependency>
    148 
    149     </dependencies>
    150 
    151 
    152     <build>
    153         <plugins>
    154             <!-- define the project compile level -->
    155             <plugin>
    156                 <groupId>org.apache.maven.plugins</groupId>
    157                 <artifactId>maven-compiler-plugin</artifactId>
    158                 <version>${maven.compiler.plugin.version}</version>
    159                 <configuration>
    160                     <source>${jdk.version}</source>
    161                     <target>${jdk.version}</target>
    162                 </configuration>
    163             </plugin>
    164         </plugins>
    165         <finalName>test-ajax-cross</finalName>
    166     </build>
    167 
    168 </project>
    View Code

        

        2、新建一个测试controller,注意返回的是一个json对象,项目中需要加入json依赖

     1 package com.test.ajax.cross.controller;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 import javax.servlet.http.HttpServletRequest;
     7 
     8 import org.springframework.stereotype.Controller;
     9 import org.springframework.web.bind.annotation.RequestMapping;
    10 import org.springframework.web.bind.annotation.ResponseBody;
    11 import org.springframework.web.servlet.ModelAndView;
    12 
    13 @Controller
    14 @RequestMapping("/test")
    15 public class TestController {
    16 
    17     @RequestMapping(value="/get")
    18     @ResponseBody
    19     public Map getTest(HttpServletRequest request){
    20         Map<String, Object> map = new HashMap();
    21         map.put("data", "TestController getTest()");
    22         return map;
    23     }
    24 }

        3、新建一个测试界面webapp/static/test.html

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Insert title here</title>
     6 <script src="jquery-1.11.3.min.js" type="text/javascript"></script>
     7 </head>
     8 <body>
     9     <h2>测试界面</h2>
    10     <a href="#" onclick="get()">发送get请求</a>
    11 </body>
    12 <script type="text/javascript">
    13     function get(){
    14         $.getJSON("http://localhost:8080/test-ajax-cross/test/get").then(function(result){
    15             console.log(result);
    16             $("body").append("<br>" + JSON.stringify(result));
    17         });
    18     }
    19 </script>
    20 </html>

         4、将项目发布到Tomcat中,并访问测试界面,http://localhost:8080/test-ajax-cross/static/test.html

          

        5、修改hosts文件(用来映射域名与IP),将a.com映射到127.0.0.1,在使用地址:http://a.com:8080/test-ajax-cross/static/test.html#,访问,可以看到无法完成ajax请求了

          

      解决方案一(禁止浏览器检查)

        禁止浏览器检查,启动浏览器时,添加参数禁止浏览器对ajax做检查

        windows采用以下方式打开谷歌浏览器

    "C:UsersUserNameAppDataLocalGoogleChromeApplicationchrome.exe" --disable-web-security --user-data-dir
    //不知道chrome.exe 地址的话
    右键chrome图标-->属性-->如下图-->图中 目标 就是文件的位置了,直接复制出来即可

        mac采用以下方式打开谷歌浏览器

    //chrome 浏览器
    open -a "Google Chrome" --args --disable-web-security  --user-data-dir
    //safari 浏览器 
    open -a '/Applications/Safari.app' --args --disable-web-security --user-data-dir 

        输入地址:http://localhost:8080/test-ajax-cross/static/test.html#,进行访问,可以看到能正常完成ajax请求了

          

      解决方案二(使用JSONP)

        Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

        JSONP的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来

      当通过<script>元素调用数据时,响应内容必须用javascript函数名和圆括号包裹起来。而不是发送这样一段JSON数据,这就是JSONP中P的意义所在

        在实践中,支持JSONP的服务不会强制指定客户端必须实现的回调函数名称,比如handleResponse。相反,它们使用査询参数的值,允许客户端指定一个函数名,然后使用函数名去填充响应。许多支持JSONP的服务都能分辨出这个参数名。另一个常见的参数名称是callback,为了让使用到的服务支持类似特殊的需求,就需要在代码上做一些修改了

        JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据

        1、修改Java后台TestController类,增加jsonp的响应返回

     1 package com.test.ajax.cross.controller;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 import javax.servlet.http.HttpServletRequest;
     7 
     8 import org.springframework.stereotype.Controller;
     9 import org.springframework.web.bind.annotation.RequestMapping;
    10 import org.springframework.web.bind.annotation.ResponseBody;
    11 import org.springframework.web.servlet.ModelAndView;
    12 
    13 import com.fasterxml.jackson.core.JsonProcessingException;
    14 import com.fasterxml.jackson.databind.ObjectMapper;
    15 
    16 @Controller
    17 @RequestMapping("/test")
    18 public class TestController {
    19     
    20     private ObjectMapper objectMapper = new ObjectMapper();
    21 
    22     @RequestMapping(value="/get")
    23     @ResponseBody
    24     public Map getTest(HttpServletRequest request){
    25         Map<String, Object> map = new HashMap();
    26         map.put("data", "TestController getTest()");
    27         return map;
    28     }
    29     
    30     @RequestMapping(value="/getJsonp")
    31     @ResponseBody
    32     public String getJsonp(HttpServletRequest request) throws JsonProcessingException{
    33         // 与前端约定好回调方法名称,默认是callback
    34         String callback = request.getParameter("callback");
    35         Map<String, Object> map = new HashMap();
    36         map.put("data", "TestController getTest()");
    37         String ret = callback+"("+ objectMapper.writeValueAsString(map)+")";
    38         return ret;
    39     }
    40 }

        2、新建一个测试界面webapp/static/test2.html,用于jsonp请求,

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Insert title here</title>
     6 <script src="jquery-1.11.3.min.js" type="text/javascript"></script>
     7 </head>
     8 <body>
     9     <h2>测试jsonp界面</h2>
    10     <a href="#" onclick="get()">发送get请求</a>
    11 </body>
    12 <script type="text/javascript">
    13     function get(){
    14         
    15         $.ajax({
    16             url: "http://localhost:8080/test-ajax-cross/test/getJsonp",
    17             dataType: "jsonp",
    18             jsonp:"callback", // 默认值是callback,可以修改
    19             success: function (result) {
    20                 console.log(result);
    21                 $("body").append("<br>" + JSON.stringify(result));
    22             }
    23         });
    24     }
    25 </script>
    26 </html>

        3、浏览器中输入地址:http://a.com:8080/test-ajax-cross/static/test2.html#,进行访问

          观察:使用F12查看请求

          参数callback对应的值是,请求响应后的回调方法

          参数_作用,值是随机数,为了是请求不使用缓存

          返回内容是:jQuery111306019926935268467_1567783875359({"data":"TestController getTest()"})

          

            

          注意:JSONP的弊端

        • 服务器需要改动代码支持
        • 只支持GET
        • 发送的不是XHR请求

          

  • 相关阅读:
    教师派10
    教师派9
    简单理解socket(AF_INET&SOCK_STREAM,SOCK_DGRAM)
    Deepin安装MySQL(MariaDB)不提示设置密码问题(密码为空)
    经典排序算法-附python代码
    Linux虚拟环境virtualevn
    linux安装虚拟环境
    deepin安装虚拟环境virtualenv
    deepin安装虚拟环境virtualenv
    把握AFNet网络请求完成的正确时机
  • 原文地址:https://www.cnblogs.com/h--d/p/11470534.html
Copyright © 2020-2023  润新知