HTTPS 在 HTTP 的基础上增加了 SSL/TLS 加密, 提供了更加安全的传输协议俨然已经属于各大网站的标配有赞作为一个 SaaS 平台, 涉及到用户的商品, 交易, 支付等关键性流程支持全站 HTTPS, 提高网站安全是我们的基础保障本文关注的事情包括: 了解 HTTPS 基础原理, 切换 HTTPS 需要切换的内容, 如何监控和实际操作, 以及遇到的一些难点
一基本原理
在原有 HTTPS 握手的基础上, 增加了证书的验证, 进行了加密, 这样我们传输数据就有安全的保证解决的问题包括运营商劫持中间人攻击钓鱼网站提升 SEO 等具体流程如下:
客户端发送 ClientHello 消息, 消息包含 SSL 的版本客户端支持的加密套件和数据压缩算法及随机数 1
服务器响应 ServerHello 消息, 消息包含选定的加密套件选定的数据压缩方法会话标识, 数字证书及另一个随机数 2
客户端 ( web 浏览器) 验证服务器的 SSL 数字证书的有效性, 不通过则提示警告
客户端发送客户端密钥交换消息此消息包含 pre-master secret(用于生成对称加密密钥生的随机数 3)
客户端使用一系列加密运算将 [随机数 1 随机数 2 随机数 3] 转化为 master secret, 其中将派生出所有用于加密和消息认证的密钥
服务器使用一系列加密运算将 [随机数 1 随机数 2 随机数 3] 转化为 master secret, 其中将派生出所有用于加密和消息认证的密钥
客户端发出更改密码规范通知服务器端之后使用协商好的对称加密算法及密钥通信
服务器发出更改密码规范通知客户端之后使用协商好的对称加密算法及密钥通信
SSL 握手结束, 使用对称加密算法进行加密通信
二 切换涉及的资源和服务
当你开始着手切换成 HTTPS 的工作时, 首先你需要明确你要处理的内容有什么? 一般来说你需要梳理以下内容:
部署到 CDN 的静态资源, jsCSS
图片资源
主域及其次级域名的数量
是否有第三方资源, 比如广告视频等接入
API 调用, 是否动态返回 HTTP 业务
提供的对外服务
关于第 1 点, 静态资源基本会收敛于少数域名, 服务也基本会由第三方 CDN 服务商提供 对应的服务提供商处开启 HTTPS 支持
动态引入静态资源
<link rel="stylesheet" href="${loadStaticContent(www/css/main.min.css)}"><script type="text/javascript" src="${loadStaticContent(www/js/main.min.js)}"></script>
在早期全站加载静态资源过程中, 应该自定义前端模板方法去动态加载 js,css 防止写死域名情况后期在全站切 CDN 域名时, 就可以直接使用新的 HTTPS 域名, 一刀切, 修改模板方法引入域名和路径
关于第 2 点, 图片来源一般分为两种, 站内图片和站外图片站内图片, 基本会使用第三方 CDN 服务可以统一开启 HTTPS 而站外图片一般的来源可能包括: 开发写死, 对接第三方服务(类似淘宝导购), 链接型图片上传未存储到自己的服务
css 动态引入图片
.loading { background-image: image-cdn('/logo_loading.png');}
假设使用了 sass 等工具, 站内图片可以在 css 中引入 CDN 域名加载方法统一替换
老图片问题
对于老的 HTTP 数据图片数据, 业务访问可知的情况下, 需要跑脚本重新上传对于上传图片组件若传入的是 HTTP 图片, 应该考虑重新上传支持
关于第 3 点, 主域及其次级域名, 可以通过统计 nginx 日志上 HTTP 的流量 (awk 日志) 获取现有站点 HTTP 流量的 pv 访问表得到需要 HTTPS 的域名的数量确认切换 HTTPS 顺序和工期, 考虑因素包括: 请求量的大小
业务的轻重缓急
业务切换 HTTPS 难度
各域名功能等方面在确定站点基本情况后, 需要和各业务方交流以上方面问题得出各域名切换的时间节点
关于第 4 点, 第三方资源引入问题
视频应该使用引入支持 HTTPS 的视频资源, 比如腾讯视频
外站不支持 HTTPS 图片, 应该考虑重传为站内图片
广告对接, 一般是引入第三方广告脚本, 第三方脚本做什么事情, 都属于第三方脚本的工作, 所以需要脚本提供方提供 HTTPS 服务
原则上第三方资源应该是 HTTPS 的, 如果不是, 我们可能就需要存储到自己的服务上或者通过服务端转发否则必然是 HTTPS 的环境下, 引入 HTTP 的情况
关于第 5 点, 属于业务范畴, 前端走 API 方式的调用, 返回值中针对头像展示图片等图片方式, 如果经过模板层可以考虑加模板方式统一替换成 HTTPS, 直接拼装成的字符串可以提供统一方法替换
关于第 6 点 , 比如你有 API 等对外服务早期开放了 HTTP 调用的口子, 那么很遗憾我们能做的事情是通过公告邮件等方式告知第三方, 我们在特定时间后就不在支持 HTTP 服务, 希望第三方支持 HTTPS 调用或者如果安全性不重要的话, 那么就同时支持 HTTP/HTTPS 调用苹果 HTTPS 的公告 App Transport Security 就是很好的例子, 而实际上 App 内部还是留了开启
HTTP 请求的设置
以上是需要我们处理的大部分内容在推进全站 HTTPS 问题之前, 做好这步梳理准备包括了调研确认切换范围
了解业务切换难易程度
确定工作的时间安排和参与人员
注: 各部分工作设定好 deadline, 会对你有非常大的帮助
三切换 HTTPS 中的注意点
站内 HTTPS 资源准备完毕后, 就可以考虑将各站点切换成 HTTPS 操作层面需要注意以下几点:
相对协议
代码层面对明显写死的 HTTP 协议进行修改修改成相对协议是不错的选择
<img src="//domain.com/img/logo.png"><script src="//www/js/libs/jquery/1.4.2/jquery.js"></script>
相对协议下, 当你访问 HTTPS 网站时, 请求 HTTPS 资源, 否则 HTTP 这样方案上更具有灵活性, 可以考虑内网先进行 HTTPS 的测试, 对外网使用 HTTP 假设 HTTPS 方案出现问题时, 可退回到 HTTP
301 与 302 区别
当页面所有资源都切换成 HTTPS, 回归测试后可考虑 HTTP 访问网站时, nginx
302
重定向到 HTTPS 强制切换上线后可经过几天到一周的观察 (流量大和复杂业务需要更久) 业务稳定, 无异常及用户反馈情况可以强制
301
切换
302 和 301 的区别就在于: 302 重定向是临时的, 下次浏览器访问同样是访问原链接而 301 重定向是持久的下次浏览器会直接访问新链接所以当确定某域名下已经实现了 HTTPS, 可采用 301 重定向
Content-Security-Policy
当某站点已经切换成了 HTTPS 假设后期还是有开发人员引入 HTTP 的情况我们应该采用哪种 CSP 策略防止呢?
block-all-mixed-content
, 强制阻止页面内 HTTP 加载
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
但是实际上, 阻止 HTTP 加载不是我们的目的, 后期开发中引入 HTTP 的行为可能是疏漏造成的, 我们可以理解成实际上资源已经可以支持 HTTPS 的 所以可以采用另一种 CSP 策略:
- upgrade-insecure-requests
- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
该策略下会产生以下两种效果
站点内的 HTTP 请求, 都会 HTTPS 的方式发起
所有连接跳转都会以 HTTPS 的方式打开
这种策略显然更加友好当网站已经确认强制使用了 HTTPS, 就可以加入该方法
测试环境是否启用 HTTPS
从测试便利性角度, 测试环境可以提供 HTTP 但实际上为了和正式环境一致应该用 HTTPS 测试更合理因为上述推荐使用相对协议, 所以测试环境本身是可以提供 HTTP/HTTPS 两种方案的
四遇到的难点
来源: https://segmentfault.com/a/1190000013635363