HTTPS跨越问题处理方法
HTTPS 在 HTTP 的基础上增加了 SSL/TLS 加密,提供了更加安全的传输协议,俨然已经属于各大网站的标配。HTTPS 在原有 HTTP 握手的基础上,增加了证书的验证,进行了加密,解决的问题包括运营商劫持、中间人攻击、钓鱼网站、提升 SEO 等。
1. 同源策略之使用不同的协议
问题起因:两个服务使用的同一域名但不同协议
- 因为公司有一个产品需要在网站内部引入外部文档,提供的是 HTTP 的地址。我们测试环境使用的也是 HTTP 的网址,所以测试不存在问题,可以正常显示外部文档内容。但是更新到正式环境之后,发现原本能够访问的文档不能访问。后来发现我们正式环境使用的是 HTTPS 的域名,因为浏览器同源策略的问题导致无法访问。
问题经过:配置 Nginx 服务间接使用
- 因为浏览器同源策略的问题,导致在 HTTPS 的网站中无法引用 HTTP 网站的资源。所以,只能配置 Nginx 使访问的时候,间接的通过代理的方式来访问对应的资源。
server { listen 443 default ssl; server_nam xxx.xxx.com; ssl_certificate "/etc/ssl/certs/xxx.crt"; ssl_trusted_certificate "/etc/ssl/certs/xxx.crt"; ssl_certificate_key "/etc/ssl/private/xxx.key"; ...... location /xxx/xxx/ { proxy_pass_header Server; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header Referer "http://www.xxx.xxx"; proxy_http_version 1.1; proxy_pass http://www.xxx.xxx; } }
- 但是配置之后发现还是无法正常显示引用的外部文档,通过浏览器自带的控制台,发现基本和之前的情况是一样的,还是显示是因为同源策略导致的。后来,通过 curl 测试发现,在访问的时候,经过了一次 302 跳转。很奇怪,为什么还需要跳转呢?
- 通过浏览器自带的控制台,再次对请求进行分析,发现 proxy_pass 代理的 http://www.xxx.xxx 网站 302 到了 http://www3.xxx.xxx 上面,这时候才真正的得到了 200 的文件内容。所以,对 Nginx 配置进行了调整。将 proxy_pass 的地址改到了真正的服务域名上面,即可。
location /xxx/xxx/ { proxy_pass_header Server; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header Referer "http://www.xxx.xxx"; proxy_http_version 1.1; proxy_pass http://www3.xxx.xxx; }
- 重载配置文件,访问内容,正常了。后来发现是数据库中存储的就是一个假地址,很是尴尬。
2. 同源策略之 Cookie 无法读取
问题起因:两个服务使用的不同域名且不同协议
- 需要部署了两个系统,A 系统和 B 系统,其中 B 系统需要通过 iframe 的方式嵌入到 A 系统中,通过配置单点登录的方式,使用户通过 A 系统来使用 B 系统的服务。但是,等到服务配置完成之后,点击跳转的时候提示 401 错误。排除了,Token 过期和用户没有登录的可能,那就一定是权限哪里配置存在了问题。
问题经过:配置 Nginx 服务间接使用
- 排查问题时发现,在 iframe 中确实是正确配置了相关单点登录的跳转地址,且本地直接访问地址是可以通过测试的,但是通过 Network 发现,紧接着有 302 跳转了一次,随即提示 401 权限错误。
- 发现要是 iframe 的地址和父级的地址不同源,项目登录时无法设置 cookie,则就是因为这个原因导致请求在 302 跳转之后出现了权限问题(没有把设置的 cookie 信息带过去)。
- 从 Chrome51 开始,浏览器的 cookie 新增加了一个 SameSite 属性,用来防止 CSRF 攻击和用户追踪。该设置当前默认是关闭的,但在 Chrome80 之后,该功能默认已开启。所以当你无法使用某些网站第三方登录功能的时候,请查看一下是否受到了该设置的影响。
# 接口设置cookie时提示 this set-cookie didnot specify a "sameSite" attribute and was defaulted to "sameSite=Lax" and broke the same rules specified in the SameSiteLax value
- 解决方法一 打开 Chrome 设置禁用对应配置项,然后重启浏览器。
- 解决方法二 通过在 Nginx 中代理相关请求到 B 系统上,来间接使用并避免同源策略导致的登录异常问题。
location /xxx/xxx/ { proxy_http_version 1.1; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://www.xxx.xxx;
3. 关于同源策略的相关科普
[1] 什么是同源策略?
- 同源策略 SOP(Same origin policy) 是一种约定,由 Netscape 公司 1995 年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS 、 CSFR等攻击。所谓同源是指 “协议+域名+端口” 三者相同,即便两个不同的域名指向同一个 IP 地址,也非同源。
URL 说明 是否允许通信 http://www.domain.com/a.js http://www.domain.com/b.js 同一域名,不同文件或路径 允许 http://www.domain.com/lab/c.js http://www.domain.com:8000/a.js http://www.domain.com/b.js 同一域名,不同端口 不允许 http://www.domain.com/a.js https://www.domain.com/b.js 同一域名,不同协议 不允许 http://www.domain.com/a.js http://192.168.4.12/b.js 域名和域名对应相同ip 不允许 http://www.domain.com/a.js http://x.domain.com/b.js 主域相同,子域不同 不允许 http://domain.com/c.js http://www.domain1.com/a.js http://www.domain2.com/b.js 不同域名 不允许
[2] 同源策略限制那些行为?
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM 和 JS对象无法获得
- AJAX 请求不能发送
[3] 跨域解决方案
- 通过jsonp跨域
- document.domain + iframe跨域
- location.hash + iframe
- window.name + iframe跨域
- postMessage跨域
- 跨域资源共享(CORS)
- Nginx代理跨域
- NodeJS中间件代理跨域
- WebSocket协议跨域
4. 最后陈述总结
比如你有 API 等对外服务,早期开放了 HTTP 调用的接口。那么很遗憾,当我们升级到 HTTPS 的时候,能做的事情是通过公告、邮件等方式告知第三方,我们在特定时间后就不在支持 HTTP 服务,希望第三方支持 HTTPS 调用。或者如果安全性不重要的话,那么就同时支持 HTTP/HTTPS 调用。苹果 HTTPS 的公告 App Transport Security 就是很好的例子,而实际上 App 内部还是留了开启 HTTP 请求的设置。
5. 参考链接记录
送人玫瑰,手有余香!