https中引入http资源资源所导致的问题
问题描述
因为公司要求所有生产环境为了安全性需求,全部都走https, 并且在Nginx里面加入了Content-Security-Policy "upgrade-insecure-requests;connect-src *响应头, 作用是让浏览器自动升级请求,防止访问者访问不安全的内容。
该指令用于让浏览器自动升级请求从http到https,用于大量包含http资源的http网页直接升级到https.虽然这样让http升级为https,但是导致出现的问题是,之前加载http资源的
图片显示不了
,样式,js加载不了
, 写在本地还行,但如果是公共的js文件,往往就是存在cdn或者其他服务器上, 这时候如果访问不了,可能导致业务完全操作不了, 比如: jquery加载失效,所有操作,请求都将无效了
https和http共存场景
https是当下的网站的主流趋势,甚至像苹果这样的大公司,则完全要求用户必须使用https地址。
然而对于以前http链接来说,我们往往就存在一个兼容性问题,因为你不可能一下就全部切换过去,应该在很长一段时间内,https与http将共存。
https与http共存场景如:
/*
1. app已经发布出去,其调用接口的地址为http的,那么这是必须兼容的。
2. app中嵌入了h5页面,而这页面在以前的设计中是使用http访问的,如果换成https地址,极有可能将导致h5页面无法打开。
3. 对于流量推广一类的业务,可能原有的http推广地址已经发送给第三方,而且即使你通知到第三方要求改为https,也不排除有http地址的访问,或者第三方不愿意改.
*/
问题分析
http协议与https协议区别
解决这个问题之前首先要知道https和http是什么, 区别在哪里.
https
它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息,它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版。它是由Netscape开发并内置于其浏览器中,用于对数据进行压缩和解压操作,并返回网络上传送回的结果。HTTPS实际上应用了Netscape的安全全套接字层(SSL)作为HTTP应用层的子层。(HTTPS使用端口443,而不是象HTTP那样使用端口80来和TCP/IP进行通信。)SSL使用40 位关键字作为RC4流加密算法,这对于商业信息的加密是合适的。HTTPS和SSL支持使用X.509数字认证,如果需要的话用户可以确认发送者是谁。总的来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议要比http协议安全。
在URL前加
https://
前缀表明是用SSL加密的,你的电脑与服务器之间收发的信息传输将更加安全。 Web服务器启用SSL需要获得一个服务器证书并将该证书与要使用SSL的服务器绑定。
https与http区别
/*
1. https协议需要到ca申请证书,一般免费证书很少,需要交费。
2. http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
3. http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。
4. http的连接很简单,是无状态的。
5. HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全。
*/
混合内容
当用户访问使用https页面时, 他们与web服务器之间的连接是使用SSL加密的, 从而保护连接不受嗅探和中间人攻击.
如果https页面包括由普通明文http连接加密的内容, 那么连接只是被部分加密; 非加密的内容可以被嗅探者入侵, 并且可以被中间人攻击者修改,因此连接不再受保护. 当一个页面出现这种情况时, 他被称为混合内容页面.
在浏览器中访问https页面时,如果该htpps页面中有一些http资源,我们可以把这些http资源,叫做混合内容(Mixed Content)。htpps页面在显示“混合内容”时候,会出现以下问题:
1、加载了混合内容,但会出现警告;
2、不加载混合内容,直接会显示空白内容;
3、 在加载混合内容之前,会出现类似是否“显示”,或存在不安全风险而被“阻止”的提示!
浏览器出现以上混合内容显示的问题,是因为https协议请求的站点,读取的资源文件js、css、图片、音视频,甚至包括请求post和get,还有iframe的页面,都必须是https协议的。这是由于https协议传输的页面比http更加安全可靠,为了保持https页面安全的一致性而作出的反应。
但https页面加载混合内容导致的问题带来的用户体验确实不太好,给用户造成了一定的麻烦,为了解决https页面加载http资源出现的问题,我们可以通过以下几种方式加以改进!
解决办法
改https初看起来,其实就是一个域名指向的问题,也许我们只要将http的请求,直接跳转到https地址去,那么也就完成了https的切换。实际并不是这么简单的。
因为https地址中,如果加载了http资源,浏览器将认为这是不安全的资源,将会默认阻止,这就会给你带来资源不全的问题了,比如:图片显示不了,样式加载不了,JS加载不了.
我们虽然可以将http请求直接跳转至https请求,是一种解决办法, 而且很多公司都是这么干的,比如百度什么的,但是前提是,你所有的服务都已切换https完成。
如果说我们要兼容https,http两种协议,应该怎样做尼?
最笨办法
直接复制原有代码, 写成两套代码,一套为https使用,一套为http使用,http和https各自指向各自服务
全站http换成https
将所有页面中的图片、视频、音乐、js,css,ajax等带有http的资源换成https方式,但要注意,有些外部http资源,如果没有https方式,直接换成https就会出现问题,最好还是下载到本地来实现!
这种方式比较适用于那些http资源不是太多,或容易更换成https的网站.
可用办法
用同一套代码, 在后台请求标识好协议,将变量传到html页面, 进行协议替换, 如: 后台变量, ,$protocol = 'https://'; 前台接收变量 src='{$protocol}res.aa.com/jquery.js'.
h5办法
. h5方法,使用js自己加载协议情况,如在body onload='aa()', 在aa() 方法中,将资源按照需求加载进来即可。
使用iframe
使用 iframe 的方式引入 http 资源,比如在 https 里面播放优酷的视频,我们可以先在一个 http 的页面里播放优酷视频,然后将这个页面嵌入到 https 页面里就可以了。
另外一个典型的例子是在 https 页面里通过 Ajax 的方式请求 http 资源,Chrome 是不允许直接 Ajax 请求 http 的。如果两个页面的内容都可以控制的话,当前窗口可以 iframe 窗口进行通信。
其他用法
这个小技巧同样适用于 CSS
.omg { background: url(//test/kittyonadolphin.gif); }
推荐办法
相对协议, 如果你的网站同时准备了https资源和http资源, 那么使用相对协议可以实现根据当前网站的协议,浏览器自行通过https还是http发送请求,使用资源协议自适配,比如,当前为https页面,那么就是https资源,如果是http页面,那么就是http资源。具体方法超简单:将URL的协议(http,https去掉)
`