前端跨域的一些小细碎

开完组会,OKOK!继续复习!今天来复习下跨域这块儿的一些问题吧.

说到跨域,那么就掰扯掰扯同源起.

同源策略:

同源,需要协议,域名以及端口都相同.其目的是为了保障用户的信息安全,防止恶意网站窃取数据.

我们来举个例子吧:

对于网站http://www.excce.com/dir/page.html,协议是http://,域名是www.excce.com,端口是80.那么下面这些是否为同源呢?

http://www.excce.com/dir1/concat.html(同源)

http://excce.com/dir/page.html(不同源,域名不同)

https://www.excce.com/dir/page.html(不同源,协议不同)

http://www.excce.com:81/dir/page.html(不同源,端口不同)

那么,我们接下来来说下,非同源有哪些操作会被限制?

1.Ajax的请求不可发送

2.DOM的读取

3.localstorage,cookie以及IndexDB无法获取

那么,有哪些又不会被非同源给限制操作呢?

1.重定向

2.表单form的提交

3.页面中的链接

4.跨域资源引入,js可加载但是不可读写内容,比如:<script src="..."></script>、<img>、<iframe>、<link>。

注意,若在标签里加入crossOrigin属性,并且服务器允许跨域后,会得到精确的报错消息;若是服务器不允许跨域,就会被同源策略阻止加载资源。若是不添加这个属性,只能知道报错,不知道具体信息。

注意,上述的这些特点,这对于我们接下来说的跨域,有很重要的铺垫哈哈.

接下来,我们来讲述下前端的几种常用的跨域方式:

1.JSONP

JSONP的话,主要就是利用了script标签没有跨域限制的这个特性来完成的.它的理念就是,与服务端约定好一个回调函数名,服务端接收到请求后,将返回一段JS,在这段JS代码中调用了约定好的回调函数,并且将数据作为参数进行传递.当网页接收到这段JS代码后,就会执行这个回调函数,这时数据已经成功传输到客户端了.当然,它有个缺点就是它只能够用get方式,如果要使用完整的rest接口的话,那还是用cors.

接下来,我们来看看cors

2.CORS

CORS是一种机制,它使用额外的http头来告诉浏览器让运行在一个origin上的web应用被准许访问来自不同源的资源.它允许浏览器向跨源服务器发送XMLHttpRequest请求,从而克服Ajax只能同源使用的限制.CORS通信与同源的ajax没什么差别,浏览器一旦发现ajax请求跨域,就会自动添加一些附加的头,有时还会多出一次附加请求.因此实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信.

简单请求:

1.get,head,post

2.人为设置一下集合外的请求头:accept,accept-language,content-language,content-type,last-event-id,content-type

除此之外的都是非简单请求.对于简单请求而言,浏览器直接发出CORS请求,就是在头信息之中,增加一个Origin.之后,服务器会根据这个值,来决定是否同意这个请求.若Origin中的这个源,并非在许可范围内,服务器会返回一个正常的HTTP回应.若Origin指定的域名在许可范围内的话,服务器返回的响应,就会多出几个头信息字段了.这三个与CORS请求相关的字段,都是以Access-Control-来开头:

1.Access-Control-Allow-Origin,该字段是必须存在的,它的值要么是请求的时候Origin字段的值,要么就是一个*,表示接受任意域名的请求.

2.Access-Control-Expose-Headers:该字段可选,CORS请求时,XHR对象的getResponseHeader()方法只能拿到六个基本字段,比如强缓存中的Cache-Control.

3.Access-Control-Allow-Credentials:该字段可选,它的值是一个布尔值,他表示是否允许发送Cookie。默认情况下,Cookie不包括再CORS请求之中,设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发送给服务器。这个值也只能设置为true,不需要的话删除即可。

withCredentials属性:

上面说到,CORS请求默认不发送Cookie与HTTP认证信息,如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。而另一方面,我们也需要在AJAX请求中打开withCredentials属性.

 

var xhr= new XMLHttpRequest();
xhr.withCredentials = true;

 

否则,即使服务器同意发送Cookie,浏览器也不会发送.或者,服务器要求设置Cookie,浏览器也不会处理.需要注意一点,如果要发送Cookie,Access-Control-Allow-Origin就不可以设置为星号了,必须必须指定明确的,与请求网页一致的域名.

3.window.postMessage

这个方法可以安全地实现跨源通信,通常两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议,端口号,以及主机时,这两个脚本才能相互通信.

4.document.domain+Iframe

该方式只能用于二级域名相同的情况下,比如a.ces.com与b.ces.com就可以用在这里.

5.window.location.hash + Iframe

原理就是通过url带hash,通过一个非跨域的中间页面来传递数据.

比如有a.html,b.html以及c.html,a与b是同域的,比如都是http://local:8000,c.html是http://local:8081.整个流程的话呢,一开始a.html给c.html传一个hash值,然后c.html将收到的hash值给b,最后n.html将结果放到a.html的hash值中.

6.window.name+Iframe

window对象的name属性是一个很特别的属性,当该window的location变化,然后重新加载,它的name属性可以依然保持不变.

既然前面,提到了Ajax跨域带Cookie的问题,我们就来跟着简单复习下Cookie,localstorage以及sessionstorage.

Cookie是存储在用户本地终端上的数据,它的大小限制为4KB左右,有时候也用Cookie让网站辨别用户身份.它可以设置失效时间,默认是关闭浏览器后就失效了,它每次都会携带再HTTP请求头中,若使用cookie保存过多数据会带来性能的问题.

localstorage的话是h5中新加入的技术,localStorage是存储在客户端中的,不参与与服务器的通信,它会永久性的保存,除非被清除,内存数据大小在5MB左右.sessionStorage与localStorage的接口类似,但是保存数据的生命周期却不相同.sessionStorage的话,只是可以将一部分数据在当前会话中保存下来,刷新页面数据依旧存下但当页面关闭后,sessionStorage中的数据就会被清空.

再简单说下应用场景吧:

因为每个HTTP请求都会带着Cookie的信息,因此Cookie当然是能多精简就多精简咯.我们常可以用到判断用户是否登陆,针对登陆过用户,服务器端会在他登陆时网Cookie中插入一段加密过的唯一辨识单一用户的辨识码,下次只要读取这个值就可以判断当前用户是否登陆过啦.

localStorage的话可以用于如HTML5游戏通常会产生一些本地数据.sessionStorage的话,如果遇到一些内容特别多的表单,我们可以把表单页面拆分成多个子页面,然后按步骤引导用户填写,这时候sessionStorage了.

需要注意一点,无论是什么数据都可以放在前三者中,但是使用它们的时候,需要注意,是否存在XSS注入的风险,只要打开控制台,随意修改它们值的时候,就可能会有XSS的风险.这里再啰嗦的说下前端的一些常见安全问题好啦.

1.XSS:

XSS是cross-site scripting,跨域脚本攻击.其攻击是指攻击者向web页面里插入恶意HTML标签或者JS代码.比如,攻击者在论坛中放入一个看似安全的链接来骗取用户cookie中的账密信息,或者在论坛中加入一个恶意表单来骗取用户而获取想要得到的信息.若要防范XSS的话,可以采取在代码里对用户输入的地方仔细检查并且对<script>、<img>、<a>等进行过滤,或者,把任何内容写到页面之前都必须进行编码,避免泄露htmltag.

2.CSRF

CSRF,即跨站点请求伪造,攻击者会诱导受害者进入第三方网站,在第三网站中向被攻击网站发送跨域请求,利用受害者在被攻击网站以获取的注册凭证,绕过后台用户的验证,达到冒充用户对被攻击的网站执行某项操作的目的.它的防范的话,可以用token方式,服务器给客户端表单一个token,客户端提交的表单中带着这个token,若返回的token不合法,则拒绝掉;或者隐藏令牌,把token藏在http的head中;或者Referer验证,指的就是页面请求来源,只接受本站的请求,服务器才做响应.

3.SQL注入

SQL注入,就是将SQL命令插入在web表单,输入域名或者页面请求的查询字符串,最终达到欺骗服务器执行恶意SQL命令的作用.防范的话,我们可以对用户的输入进行校验,可以使用正则表达式来限制长度.或者对机密信息进行加密,且不要使用管理员权限的数据库连接.

原文地址:https://www.cnblogs.com/ljylearnsmore/p/14586762.html