跨域的几种常见的解决方式

今天给大家分享一下,修真院官网JSS-5任务中可能会使用到的知识点:

1.背景介绍

1.1什么是跨域?

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。


广义的跨域:
1.) 资源跳转: A链接、重定向、表单提交
2.) 资源嵌入: link script img frame等dom标签,还有样式中background:url()、@font-face()等文件外链
3.) 脚本请求: js发起的ajax请求、dom和js对象的跨域操作等


在前端部分其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。

1.2那么是什么同源策略呢?

同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。


同源策略限制以下几种行为: 1.) Cookie、LocalStorage 和 IndexDB 无法读取 2.) DOM 和 Js对象无法获得 3.) AJAX 请求不能发送

1.3常见的跨域场景

跨域的几种常见的解决方式_第1张图片

2.知识剖析

2.1 常见的跨域方式

JSONP


在使用XMLHTTPRequest对象发送HTTP请求时,会遇到同源策略问题,域不同请求会被浏览器拦截。这时就可以选择绕过,或者说是不使用XMLHTTPRequest对象进行发送跨域HTTP请求。 在平常写html时会发现比如



              
                      
这种标签是不会遇到'跨域'问题的,严格上来说,这不是跨域,跨域是指在脚本代码中向非同源域发送HTTP请求,这只是跨站资源请求

那么我们可以试试看用这种跨站资源请求的方式来实现跨域HTTP请求

                  
                        ...
                        
                        // 如果jsonp 的请求为GET
  if ( ctx.method === 'GET' && ctx.url.split('?')[0] === '/getData') {

    // 获取jsonp的callback
    let callbackName = ctx.query.callback || 'callback'
    let returnData = {
      success: true,
      data: {
        text: 'this is a jsonp api',
        time: new Date().getTime(),
      }
    }

    // jsonp的script字符串
    let jsonpStr = `;${callbackName}(${JSON.stringify(returnData)})`

    // 用text/javascript,让请求支持跨域获取
    ctx.type = 'text/javascript'

    // 输出jsonp字符串
    ctx.body = jsonpStr

  } else {

    ctx.body = 'hello jsonp'

  }
})
NGINX的反向代理

nginx支持配置反向代理,通过反向代理实现网站的负载均衡。这部分先写一个nginx的配置,后续需要深入研究nginx的代理模块和负载均衡模块。 nginx通过proxy_pass_http 配置代理站点,upstream实现负载均衡。


WINDOW.NAME + IFRAME

WINDOW.NAME 传输技术的基本原理:

当在浏览器中打开一个页面,或者在页面中添加一个iframe时即会创建一个对应的window对象,当页面加载另一个新的页面时,window的name属性是不会变的。这样就可以利用在页面动态添加一个iframe然后src加载数据页面,在数据页面将需要的数据赋值给window.name。然而此时承载iframe的parent页面还是不能直接访问,不在同一域下iframe的name属性,这时只需要将iframe再加载一个与承载页面同域的空白页面,即可对window.name进行数据读取

name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。同源策略依旧防止其他 frame 访问 name 属性。一旦 name 属性获得,销毁 frame 。

在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性


也可以node.js或者其他服务端设置cors表头来授权跨域


3.常见问题


4.解决方案


5.编码实战


6.拓展思考

6.1正向代理



正向代理类似一个跳板机,代理访问外部资源。




 我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

  客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的IP地址,还有代理程序的端口。

总结来说:正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。   
正向代理的用途:
  (1)访问原来无法访问的资源,如google
(2) 可以做缓存,加速访问资源
  (3)对客户端访问授权,上网进行认证

  (4)代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

6.2反向代理


客户端是无感知代理的存在的,反向代理对外都是透明的,访问者者并不知道自己访问的是一个代理。因为客户端不需要任何配置就可以访问。
  反向代理(Reverse Proxy)实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
反向代理的作用:
(1)保证内网的安全,可以使用反向代理提供WAF功能,阻止web攻击

大型网站,通常将反向代理作为公网访问地址,Web服务器是内网。


(2)负载均衡,通过反向代理服务器来优化网站的负载


6.3二者的区别


借某乎上一个灵魂画手的图片解释下

7.参考文献

前端常见跨域解决方案:https://www.cnblogs.com/roam/p/7520433.html 

js中几种使用的跨域方法详解:https://www.cnblogs.com/2050/p/3191744.html

8.更多讨论

一、哪种跨域常用?

淘宝、百度、网易云音乐,之类会配置公共的API,会是JSONP

公司内的话会选择window.name或者nginx反向代理

我们任务中会使用nginx.conf进行反向代理

二、从安全性而言选择那种跨域方式最好,为什么?

一般最安全的是WINDOW.NAME,因为iframe会销毁

三、JSONP的缺点
jsonp有个缺陷就是只能get

而且会把请求的内容发送到url中导致安全性极低


你可能感兴趣的:(跨域的几种常见的解决方式)