zoukankan      html  css  js  c++  java
  • 俩种跨域方式

     


    1、先来说说什么是源
    • 源(origin)就是协议、域名和端口号。
    以上url中的源就是:http://www.company.com:80
    若地址里面的协议、域名和端口号均相同则属于同源。
    以下是相对于 http://www.a.com/test/index.html 的同源检测
    • http://www.a.com/dir/page.html ----成功
    • http://www.child.a.com/test/index.html ----失败,域名不同
    • https://www.a.com/test/index.html ----失败,协议不同
    • http://www.a.com:8080/test/index.html ----失败,端口号不同

    2.什么是同源策略?
    同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。

    • 不受同源策略限制的:
    1、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
    2、跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。

    二、跨域
    1、什么是跨域
    受前面所讲的浏览器同源策略的影响,不是同源的脚本不能操作其他源下面的对象。想要操作另一个源下的对象是就需要跨域。

    2、跨域的实现形式
    • 降域 document.domain
    同源策略认为域和子域属于不同的域,如:
    child1.a.com 与 a.com,
    child1.a.com 与 child2.a.com,
    xxx.child1.a.com 与 child1.a.com
    两两不同源,可以通过设置 document.damain='a.com',浏览器就会认为它们都是同一个源。想要实现以上任意两个页面之间的通信,两个页面必须都设置documen.damain='a.com'。
    此方式的特点:
    1. 只能在父域名与子域名之间使用,且将 xxx.child1.a.com域名设置为a.com后,不能再设置成child1.a.com。
    2. 存在安全性问题,当一个站点被攻击后,另一个站点会引起安全漏洞。
    3. 这种方法只适用于 Cookie 和 iframe 窗口。

    1.1、JSONP

      JSONP是利用浏览器对script的资源引用没有同源限制,通过动态插入一个script标签,当资源加载到页面后会立即执行的原理实现跨域的。JSONP是一种非正式传输协议,该协议的一个要点就是允许用户传递一个callback或者开始就定义一个回调方法,参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
      JSONP只支持GET请求而不支持POST等其它类型的HTTP请求,它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题,JSONP的优势在于支持老式浏览器,弊端也比较明显:需要客户端和服务端定制进行开发,服务端返回的数据不能是标准的Json数据,而是callback包裹的数据。

    1.2、CORS

      CORS是现代浏览器支持跨域资源请求的一种方式,全称是"跨域资源共享"(Cross-origin resource sharing),当使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;浏览器判断该相应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
      CORS与JSONP的使用目的相同,但是比JSONP更强大,CORS支持所有的浏览器请求类型,承载的请求数据量更大,开放更简洁,服务端只需要将处理后的数据直接返回,不需要再特殊处理。

     

    二、跨域解决方案距离

    2.1、JSONP方案实现跨域

    前段AJAX请求

    复制代码
     1 $.ajax({
     2      url: "http://otherdomain.com/manage/role/get",
     3      async: false,
     4      type: "get", 5      dataType: "jsonp",
     6      data:{
     7         "id":1 
     8      },
     9      jsonp: "callback",
    10      jsonpCallback:"fn",
    11      success: function(data){
    12          alert(data.code);
    13      },
    14      error: function(){
    15          alert('fail');
    16      }
    17 })
    复制代码

    服务端响应数据

    复制代码
     1 @RequestMapping("/manage/role/get")
     2 @ResponseBody
     3 public String get(HttpServletRequest request, HttpServletResponse response) {
     4     BaseOutput outPut = new BaseOutput();
     5     try {
     6         QueryFilter filter = new QueryFilter(request);
     7         logger.info(filter.toString());
     8         String id = filter.getParam().get(MainConst.KEY_ID);
     9         if(!StringUtil.isEmpty(id)) {
    10             ImRole role = roleService.getByPk(filter);
    11             outPut.setData(role);
    12         }
    13         else {
    14             outPut.setCode(OutputCodeConst.INPUT_PARAM_IS_NOT_FULL);
    15             outPut.setMsg("The get id is needed.");
    16         }
    17     } catch (Exception e) {
    18         logger.error("获取角色数据异常!", e);
    19         outPut.setCode(OutputCodeConst.UNKNOWN_ERROR);
    20         outPut.setMsg("获取角色数据异常! " + e.getMessage());
    21     }
    22     return "fn("+JsonUtil.objectToJson(outPut)+")";
    23 }
    复制代码

    注意内容:

    1、Ajax请求需要设置请求类型为Jsonp

    dataType: "jsonp"

    2、Ajax请求需要设置回调函数,当前函数值必须与服务器响应包含的callback名称相同

    jsonpCallback:"fn"

    3、Ajax请求可以设置jsonp(可选),传递给请求处理程序或页面,用以获得jsonp回调函数名的参数名,默认为:callback

    jsonp: "callback"

    4、服务端返回Json数据必须使用jsonpCallback设置的值进行包裹

    return "fn("+JsonUtil.objectToJson(outPut)+")"

     

     


    2.2、CORS方案实现跨域

    前段AJAX请求

    复制代码
     1 function test() {
     2    $.ajax({
     3          url: "http://localhost:8080/AdsServer/manage/role/get",
     4          type: "get",
     5          async: false,
     6          data:{
     7             "id":1 
     8          },
     9          dataType:"json",
    10          withCredentials:true,
    11          success: function(data){
    12              alert(data);
    13              alert(data.code);
    14          },
    15          error: function(){
    16              alert('fail');
    17          }
    18    })
    19 }
    复制代码

     

    服务端响应数据

    复制代码
     1 @RequestMapping("/manage/role/get")
     2 @ResponseBody
     3 public String get(HttpServletRequest request, HttpServletResponse response) {
     4     BaseOutput outPut = new BaseOutput();
     5     try {
     6         QueryFilter filter = new QueryFilter(request);
     7         logger.info(filter.toString());
     8         String id = filter.getParam().get(MainConst.KEY_ID);
     9         if(!StringUtil.isEmpty(id)) {
    10             ImRole role = roleService.getByPk(filter);
    11             outPut.setData(role);
    12         }
    13         else {
    14             outPut.setCode(OutputCodeConst.INPUT_PARAM_IS_NOT_FULL);
    15             outPut.setMsg("The get id is needed.");
    16         }
    17     } catch (Exception e) {
    18         logger.error("获取角色数据异常!", e);
    19         outPut.setCode(OutputCodeConst.UNKNOWN_ERROR);
    20         outPut.setMsg("获取角色数据异常! " + e.getMessage());
    21     }
    22     return JsonUtil.objectToJson(outPut);
    23 }
    复制代码

    服务端增加过滤拦截器(web.xml)

    复制代码
    1 <filter>
    2     <filter-name>crossDomainFilter</filter-name>
    3     <filter-class>com.luwei.core.filter.CrossDomainFilter</filter-class>
    4 </filter>
    5 <filter-mapping>
    6     <filter-name>crossDomainFilter</filter-name>
    7     <url-pattern>*</url-pattern>
    8 </filter-mapping>
    复制代码

    服务端增加过滤拦截器(java)

    复制代码
     1 package com.luwei.core.filter;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.Filter;
     6 import javax.servlet.FilterChain;
     7 import javax.servlet.FilterConfig;
     8 import javax.servlet.ServletException;
     9 import javax.servlet.ServletRequest;
    10 import javax.servlet.ServletResponse;
    11 import javax.servlet.http.HttpServletRequest;
    12 import javax.servlet.http.HttpServletResponse;
    13 
    14 import org.apache.commons.lang.StringUtils;
    15 import org.slf4j.Logger;
    16 import org.slf4j.LoggerFactory;
    17 
    18 import com.luwei.console.mg.constant.ApplicationConfiConst;
    19 
    20 /**
    21  * 
    22  * <Description> TODO<br> 
    23  *  
    24  * @author lu.wei<br>
    25  * @email 1025742048@qq.com <br>
    26  * @date 2017年1月4日 <br>
    27  * @since V1.0<br>
    28  * @see com.luwei.console.mg.tag <br>
    29  */
    30 public class CrossDomainFilter implements Filter {
    31     private Logger logger = LoggerFactory.getLogger(getClass());
    32 
    33     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    34         ApplicationConfiConst confiConst = (ApplicationConfiConst) ContextUtil.getBean("applicationConfiConst");
    35         HttpServletResponse response = (HttpServletResponse) res;
    36         HttpServletRequest request = (HttpServletRequest) req;
    37         String referer = request.getHeader("referer");
    38         String origin = null;
    39         if (null != referer) {
    40             String[] domains = confiConst.getCanAccessDomain().split(",");
    41             for (String domain : domains) {
    42                 if (StringUtils.isNotEmpty(domain) && referer.startsWith(domain)) {
    43                     origin = domain;
    44                     break;
    45                 }
    46             }
    47         }
    48         response.setHeader("Access-Control-Allow-Origin", origin);
    49         response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PATCH");
    50         response.setHeader("Access-Control-Max-Age", "3600");
    51         response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    52         // 是否支持cookie跨域
    53         response.addHeader("Access-Control-Allow-Credentials", "true");
    54 
    55         String requestURI = ((HttpServletRequest) req).getRequestURI();
    56         long begin = System.currentTimeMillis();
    57         chain.doFilter(req, res);
    58         if (logger.isDebugEnabled()) {
    59             logger.debug("[Request URI: " + requestURI + "], Cost Time:" + (System.currentTimeMillis() - begin) + "ms");
    60         }
    61     }
    62 }
    复制代码

    增加设置能够通过跨域访问的服务器地址

    #设置能够访问接口的域(多个通过都好分割)(不能配置127.0.0.1)
    CAN_ACCESS_DOMAIN=http://localhost:8020,http://localhost:9999,http://localhost:8080

     

    注意内容:

    1、Ajax请求必须要设置withCredentials属性为true

    withCredentials:true

    2、服务端需要配置过滤器,讲配置能够进行跨域访问服务器的地址进行配置

    response.setHeader("Access-Control-Allow-Origin", origin);
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PATCH");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    // 是否支持cookie跨域
    response.addHeader("Access-Control-Allow-Credentials", "true");

    3、withCredentials设置成true时,Access-Control-Allow-Origin不支持通过*的方式进行统配

    4、Access-Control-Allow-Origin不能直接配置多个请求服务器,但是可以通过静态配置多个的方式,然后根据referer匹配,匹配到哪个则设置Access-Control-Allow-Origin为哪个的方式来配置多个

     

    后记:

    jqGrid配置跨域请求的方式为:

    ajaxGridOptions: {
        xhrFields: {
            withCredentials: true
        }
    },

    、简要介绍

    1.1、JSONP

      JSONP是利用浏览器对script的资源引用没有同源限制,通过动态插入一个script标签,当资源加载到页面后会立即执行的原理实现跨域的。JSONP是一种非正式传输协议,该协议的一个要点就是允许用户传递一个callback或者开始就定义一个回调方法,参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
      JSONP只支持GET请求而不支持POST等其它类型的HTTP请求,它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题,JSONP的优势在于支持老式浏览器,弊端也比较明显:需要客户端和服务端定制进行开发,服务端返回的数据不能是标准的Json数据,而是callback包裹的数据。

    1.2、CORS

      CORS是现代浏览器支持跨域资源请求的一种方式,全称是"跨域资源共享"(Cross-origin resource sharing),当使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;浏览器判断该相应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
      CORS与JSONP的使用目的相同,但是比JSONP更强大,CORS支持所有的浏览器请求类型,承载的请求数据量更大,开放更简洁,服务端只需要将处理后的数据直接返回,不需要再特殊处理。

     

    二、跨域解决方案距离

    2.1、JSONP方案实现跨域

    前段AJAX请求

    复制代码
     1 $.ajax({
     2      url: "http://otherdomain.com/manage/role/get",
     3      async: false,
     4      type: "get", 5      dataType: "jsonp",
     6      data:{
     7         "id":1 
     8      },
     9      jsonp: "callback",
    10      jsonpCallback:"fn",
    11      success: function(data){
    12          alert(data.code);
    13      },
    14      error: function(){
    15          alert('fail');
    16      }
    17 })
    复制代码

    服务端响应数据

    复制代码
     1 @RequestMapping("/manage/role/get")
     2 @ResponseBody
     3 public String get(HttpServletRequest request, HttpServletResponse response) {
     4     BaseOutput outPut = new BaseOutput();
     5     try {
     6         QueryFilter filter = new QueryFilter(request);
     7         logger.info(filter.toString());
     8         String id = filter.getParam().get(MainConst.KEY_ID);
     9         if(!StringUtil.isEmpty(id)) {
    10             ImRole role = roleService.getByPk(filter);
    11             outPut.setData(role);
    12         }
    13         else {
    14             outPut.setCode(OutputCodeConst.INPUT_PARAM_IS_NOT_FULL);
    15             outPut.setMsg("The get id is needed.");
    16         }
    17     } catch (Exception e) {
    18         logger.error("获取角色数据异常!", e);
    19         outPut.setCode(OutputCodeConst.UNKNOWN_ERROR);
    20         outPut.setMsg("获取角色数据异常! " + e.getMessage());
    21     }
    22     return "fn("+JsonUtil.objectToJson(outPut)+")";
    23 }
    复制代码

    注意内容:

    1、Ajax请求需要设置请求类型为Jsonp

    dataType: "jsonp"

    2、Ajax请求需要设置回调函数,当前函数值必须与服务器响应包含的callback名称相同

    jsonpCallback:"fn"

    3、Ajax请求可以设置jsonp(可选),传递给请求处理程序或页面,用以获得jsonp回调函数名的参数名,默认为:callback

    jsonp: "callback"

    4、服务端返回Json数据必须使用jsonpCallback设置的值进行包裹

    return "fn("+JsonUtil.objectToJson(outPut)+")"

     

     


    2.2、CORS方案实现跨域

    前段AJAX请求

    复制代码
     1 function test() {
     2    $.ajax({
     3          url: "http://localhost:8080/AdsServer/manage/role/get",
     4          type: "get",
     5          async: false,
     6          data:{
     7             "id":1 
     8          },
     9          dataType:"json",
    10          withCredentials:true,
    11          success: function(data){
    12              alert(data);
    13              alert(data.code);
    14          },
    15          error: function(){
    16              alert('fail');
    17          }
    18    })
    19 }
    复制代码

     

    服务端响应数据

    复制代码
     1 @RequestMapping("/manage/role/get")
     2 @ResponseBody
     3 public String get(HttpServletRequest request, HttpServletResponse response) {
     4     BaseOutput outPut = new BaseOutput();
     5     try {
     6         QueryFilter filter = new QueryFilter(request);
     7         logger.info(filter.toString());
     8         String id = filter.getParam().get(MainConst.KEY_ID);
     9         if(!StringUtil.isEmpty(id)) {
    10             ImRole role = roleService.getByPk(filter);
    11             outPut.setData(role);
    12         }
    13         else {
    14             outPut.setCode(OutputCodeConst.INPUT_PARAM_IS_NOT_FULL);
    15             outPut.setMsg("The get id is needed.");
    16         }
    17     } catch (Exception e) {
    18         logger.error("获取角色数据异常!", e);
    19         outPut.setCode(OutputCodeConst.UNKNOWN_ERROR);
    20         outPut.setMsg("获取角色数据异常! " + e.getMessage());
    21     }
    22     return JsonUtil.objectToJson(outPut);
    23 }
    复制代码

    服务端增加过滤拦截器(web.xml)

    复制代码
    1 <filter>
    2     <filter-name>crossDomainFilter</filter-name>
    3     <filter-class>com.luwei.core.filter.CrossDomainFilter</filter-class>
    4 </filter>
    5 <filter-mapping>
    6     <filter-name>crossDomainFilter</filter-name>
    7     <url-pattern>*</url-pattern>
    8 </filter-mapping>
    复制代码

    服务端增加过滤拦截器(java)

    复制代码
     1 package com.luwei.core.filter;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.servlet.Filter;
     6 import javax.servlet.FilterChain;
     7 import javax.servlet.FilterConfig;
     8 import javax.servlet.ServletException;
     9 import javax.servlet.ServletRequest;
    10 import javax.servlet.ServletResponse;
    11 import javax.servlet.http.HttpServletRequest;
    12 import javax.servlet.http.HttpServletResponse;
    13 
    14 import org.apache.commons.lang.StringUtils;
    15 import org.slf4j.Logger;
    16 import org.slf4j.LoggerFactory;
    17 
    18 import com.luwei.console.mg.constant.ApplicationConfiConst;
    19 
    20 /**
    21  * 
    22  * <Description> TODO<br> 
    23  *  
    24  * @author lu.wei<br>
    25  * @email 1025742048@qq.com <br>
    26  * @date 2017年1月4日 <br>
    27  * @since V1.0<br>
    28  * @see com.luwei.console.mg.tag <br>
    29  */
    30 public class CrossDomainFilter implements Filter {
    31     private Logger logger = LoggerFactory.getLogger(getClass());
    32 
    33     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    34         ApplicationConfiConst confiConst = (ApplicationConfiConst) ContextUtil.getBean("applicationConfiConst");
    35         HttpServletResponse response = (HttpServletResponse) res;
    36         HttpServletRequest request = (HttpServletRequest) req;
    37         String referer = request.getHeader("referer");
    38         String origin = null;
    39         if (null != referer) {
    40             String[] domains = confiConst.getCanAccessDomain().split(",");
    41             for (String domain : domains) {
    42                 if (StringUtils.isNotEmpty(domain) && referer.startsWith(domain)) {
    43                     origin = domain;
    44                     break;
    45                 }
    46             }
    47         }
    48         response.setHeader("Access-Control-Allow-Origin", origin);
    49         response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PATCH");
    50         response.setHeader("Access-Control-Max-Age", "3600");
    51         response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    52         // 是否支持cookie跨域
    53         response.addHeader("Access-Control-Allow-Credentials", "true");
    54 
    55         String requestURI = ((HttpServletRequest) req).getRequestURI();
    56         long begin = System.currentTimeMillis();
    57         chain.doFilter(req, res);
    58         if (logger.isDebugEnabled()) {
    59             logger.debug("[Request URI: " + requestURI + "], Cost Time:" + (System.currentTimeMillis() - begin) + "ms");
    60         }
    61     }
    62 }
    复制代码

    增加设置能够通过跨域访问的服务器地址

    #设置能够访问接口的域(多个通过都好分割)(不能配置127.0.0.1)
    CAN_ACCESS_DOMAIN=http://localhost:8020,http://localhost:9999,http://localhost:8080

     

    注意内容:

    1、Ajax请求必须要设置withCredentials属性为true

    withCredentials:true

    2、服务端需要配置过滤器,讲配置能够进行跨域访问服务器的地址进行配置

    response.setHeader("Access-Control-Allow-Origin", origin);
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PATCH");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    // 是否支持cookie跨域
    response.addHeader("Access-Control-Allow-Credentials", "true");

    3、withCredentials设置成true时,Access-Control-Allow-Origin不支持通过*的方式进行统配

    4、Access-Control-Allow-Origin不能直接配置多个请求服务器,但是可以通过静态配置多个的方式,然后根据referer匹配,匹配到哪个则设置Access-Control-Allow-Origin为哪个的方式来配置多个

     

    后记:

    jqGrid配置跨域请求的方式为:

    ajaxGridOptions: {
        xhrFields: {
            withCredentials: true
        }
    },
  • 相关阅读:
    git stash回退
    基于git tag快速修复
    Go语言开发规范
    defer实现原理
    string数据结构
    关于const iota
    struct
    map数据结构底层详解
    go 函数进阶
    go 内存分配原理
  • 原文地址:https://www.cnblogs.com/SUNSHINEC/p/8296956.html
Copyright © 2011-2022 走看看