跨域问题

什么是跨域问题?

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面的URL具有相同的协议(protocol),主机/域名(host)和端口号(port)。

URI、URL和URN的区别

当我们打开浏览器,要访问一个网站或者一个ftp服务器的时候,输入一串字符串, 比如:https://blog.csdn.net/或者:ftp://192.168.0.111/,这样我们就可以得到一个html格式的页面或者一个文件。那么这个地址是什么意思呢?就必须要从URI、URL、URN讲起。

定义

  • URI = Uniform Resource Identifier 统一资源标志符
  • URL = Uniform Resource Locator 统一资源定位符
  • URN = Uniform Resource Name 统一资源名称

简单来说,URI是抽象的定义,不管用什么方法表示,只要能定位一个资源,就叫URI。本来设想的使用两种方法定位:1、URL,用地址定位;2、URN 用名称定位。但是urn没流行起来,导致现在大家说的所有的UR都是默认就是URL。

举个例子:去村子找个具体的人(URI),如果用地址:某村多少号房子第几间房的主人,就是URL;如果用身份证号+名字去找就是URN了。

区别

  1. URI是以一种抽象的,高层次概念定义统一资源标识,而URL则是具体的资源标识的方式。URL是一种URI。
  2. 格式不同:URL的格式一般由下列四部分组成:
    1. 第一部分是协议(或称为服务方式);
    2. 第二部分是存有该资源的主机IP地址,也叫域名;
    3. 第三部分是端口号;
    4. 第四部分是主机资源的具体地址。

3、在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的,schema(protocol,协议)必须被指定。

三者的关系

URL结构解析

URL代表着是统一资源定位符(UniformResourceLocator)。

作用是为了告诉使用者 某个资源在 Web 上的地址。比如:用HTTP协议访问Web服务器:

用FTP协议下载和上传文件的URL:

读取客户端计算机本地文件的URL:

URL的结构组成如下图:

协议

尽管 URL 有各种不同的写法, 但它们有一个共同点, 开头部分的内容必须是协议类型,可以是http、ftp、mailto或者https,这部分文字都表示浏览器应当使用的访问方法,会用‘//’为分隔符。决定了后面部分的写法, 因此并不会造成混乱。

用户名/密码

用户名密码通常可以省略。

域名

域名是www.gitee.com,在发送请求前,会向DNS服务器请求将域名字符串解析为IP地址。如果已经知道ip,还可以跳过DNS解析那一步,直接把IP当做域名部分使用。

域名是从右向左进行分析的,依次为:域名后缀、顶级域名(一级域名)、二级域名、三级域名,如图:

端口

域名后面有些时候会带有端口,和域名之间用’:’分隔,端口不是一个URL的必须的部分。 当网址为http://时,默认端口为80, https://时,默认端口是443, ftp://时,默认端口是21。此时端口号可以省略不写。

文件路径/文件名

从域名之后的第一个/开始到最后一个/为止,是虚拟目录的部分。虚拟目录也不是URL必须的部分,上述实例http协议url中的虚拟目录是:/yikoulinux/chat/blob/master/

从域名最后一个’/‘开始到’?’为止,是文件名部分;如果没有?,则是从域名最后一个/开始到#为止,是文件名部分;如果没有?和#,那么就从域名的最后一个/从开始到结束,都是文件名部分。

文件名也不是一个URL的必须部分。

Demo:判断下列URL与 http://www.example.com:8080是否是跨域?

比较的URL 是否跨域 原因
http://www.example.com:8080/dir/page.html 协议、主机/域名、端口号等相同
http://username:password@www.example.com:8080/dir/page.html 协议、主机/域名、端口号等相同
http://www.example.com:**81**/dir/page.html 跨域 端口号不相同
https://www.example.com:8080 跨域 协议不相同
http://en.example.com:8080 跨域 主机/域名不相同

请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。

解决方案

常见的几种解决方案:

  • 服务器代理

    • 让请求和响应双方url不同源,域名不同。
  • 改发JSONP

    • 将ajax请求改为JSONP
      • 不是ajax
      • 只能支持get方式
  • CORS

    • CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
    • CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10(ie8通过XDomainRequest能支持CORS)。
  • Spring MVC中提供的**@CrossOrigin注解**

    • 当域名www.abc.com下的js代码去访问www.def.com域名下的资源,就会受到限制。使用@CrossOrigin可以处理跨域请求,让你能访问不是一个域的文件。

参考文档:

什么是跨域?跨域解决方法