在项目中有遇到“跨域”,so要对跨域有个清楚认识,并对安全知识进行简单总结javascript
注:php
简述:
html
跨域:是指a页面想获取b页面资源,若是a、b页面的协议、域名、端口、子域名不一样,所进行的访问行动都是跨域的,而浏览器为了安全问题通常都限制了跨域访问,也就是不容许跨域请求资源。注意:跨域限制访问,实际上是浏览器的限制。
跨域问题:
1. jsonp能够解决
2. cors设置Access-Control-Allow-Origin头
3. nginx解决,搭建一个中转nginx服务器,用于转发请求
前端
出于浏览器的同源策略限制。java
同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,则浏览器的正常功能可能都会受到影响。能够说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另一个域的内容进行交互。nginx
同源策略限制了从同一个源加载的文档或脚本与另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
所谓同源(即指在同一个域)就是两个页面具备相同的协议(protocol),主机(host)和端口号(port)
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不一样即为跨域web
【1】没法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB算法
【2】没法接触非同源网页的 DOMjson
【3】没法向非同源地址发送 AJAX 请求segmentfault
【1】JSONP
JSONP 是服务器与客户端跨源通讯的经常使用方法。最大特色就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页经过添加一个<script>元素
,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
// 处理服务器返回回调函数的数据
<script type="text/javascript">
function dosomething(data){
//处理得到的数据
}
</script>复制代码
【2】CORS 是处理跨域问题的标准作法
原理:CORS是一个W3C标准,全称是"跨域资源共享"。它容许浏览器向跨源服务器,发出XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。它为Web服务器定义了一种方式,容许网页从不一样的域访问其资源.
CORS系统定义了一种浏览器和服务器交互的方式来肯定是否容许跨域请求。 它是一个妥协,有更大的灵活性,但比起简单地容许全部这些的要求来讲更加安全。
实现方法:
CORS须要浏览器和服务器同时支持。目前,全部浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通讯过程,都是浏览器自动完成,不须要用户参与。对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。
浏览器将CORS请求分红两类:简单请求和非简单请求。
一、简单请求:只要同时知足如下两大条件
(1) 请求方法是如下三种方法之一:
(2)HTTP的头信息不超出如下几种字段:
简单请求:只服务端设置, 在response中加header:Access-Control-Allow-Origin便可,若要带cookie请求:先后端都须要设置。
response.setHeader("Access-Control-Allow-Origin", *);
注意:*时cookie不会在http请求中带上
若是须要http请求中带上cookie,须要先后端都设置credentials,且后端设置指定的origin
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
response.setHeader("Access-Control-Allow-Credentials", "true"); 复制代码
2.非简单请求
非简单请求的cors请求,会在正式通讯以前,发出一次预检测请求,返回码是204,预检测经过才会真正发出请求,这才返回200。这里经过前端发请求的时候增长一个额外的headers来触发非简单请求。
// 若是须要http请求中带上cookie,须要先后端都设置credentials,且后端设置指定的origin
response.setHeader('Access-Control-Allow-Origin', 'http://localhost:9099')
response.setHeader('Access-Control-Allow-Credentials', true)
// 非简单请求的CORS请求,会在正式通讯以前,增长一次HTTP查询请求,称为"预检"请求(preflight)
// 这种状况下除了设置origin,
// 还须要设置Access-Control-Request-Method以及Access-Control-Request-Headers
response.setHeader('Access-Control-Request-Method', 'PUT,POST,GET,DELETE,OPTIONS')
response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, t')
复制代码
【3】nginx反向代理
想一下,若是咱们请求的时候仍是用前端的域名,而后有个东西帮咱们把这个请求转发到真正的后端域名上,不就避免跨域了吗?这时候,Nginx出场了。
实现原理相似于中间件代理,须要你搭建一个中转nginx服务器,用于转发请求。
使用nginx反向代理实现跨域,是最简单的跨域方式。只须要修改nginx的配置便可解决跨域问题,支持全部浏览器,支持session,不须要修改任何代码,而且不会影响服务器性能。
实现思路:经过nginx配置一个代理服务器(域名与domain1相同,端口不一样)作跳板机,反向代理访问domain2接口,而且能够顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登陆。
Nginx转发的方式彷佛很方便!但这种使用也是看场景的,若是后端接口是一个公共的API,好比一些公共服务获取天气什么的,前端调用的时候总不能让运维去配置一下Nginx,若是兼容性没问题(IE 10或者以上),CROS才是更通用的作法吧。
目的:我加密让别人来验,因此是私钥加签,公钥验签
数字签名,简单来讲就是经过提供可鉴别的数字信息验证自身身份的一种方式。一套数字签名一般定义两种互补的运算,一个用于签名,另外一个用于验证。即:加签、验签
分别由发送者持有可以表明本身身份的私钥 (私钥不可泄露),由接受者持有与私钥对应的公钥 ,可以在接受到来自发送者信息时用于验证其身份。
注意:正常 加密过程: 公钥加密,私钥解密。
一、签名 最根本用途是要可以惟一 证实发送方的身份,防止 中间人攻击,CSRF
跨域身份伪造
二、基于这一点在诸如 设备认证、 用户认证、 第三方认证等认证体系中都会使用 签名算法
加密cookie:A+B+C
一、拼接 byte[ ] content = A+B+C, 经过SHA256签名,获得2位验证码captcha(第二、4位)
二、对 byte[ ] encrypt = A+B 进行AES128加密
三、组合 captcha+ encrypt,再转为string,获得一个加密串result
四、最后经过 result:c 组合成结果
解密cookie
一、冒号分割,获取前半段
二、经行base64解密,获得验证码和加密串 captcha+ encrypt
三、用AES128对加密串encrypt 进行解密,获得加密详情 A+B
四、对详情 A+B+C 经过SHA256签名,获得2位验证码captcha2
五、与第2步的验证码 captcha 进行比较,相同,说明cookie正确,即返回详情
Base64编码的做用:因为某些系统中只能使用ASCII字符。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法。它使用下面表中所使用的字符与编码。
并且base64特别适合在http,mime协议下快速传输数据。
base64其实不是安全领域下的加密解密算法。虽然有时候常常看到所谓的base64加密解密。其实base64只能算是一个编码算法,对数据内容进行编码来适合传输。虽然base64编码事后原文也变成不能看到的字符格式,可是这种方式很初级,很简单。
1.前端安全
2.后端安全