好记性不如 烂笔头,趁热记录下,给未来的自己
0 | 前言
项目需求永远是学习技术最好的动力
项目中,有这样一个事务场景,作为一个平台,能够布置用户写的各种运用,比方gradio运用,streamlit运用,也能够嵌入外部网站的url,这些运用在平台上经过嵌入 iframe 去展现。
然后,针对外部网站,有许多临时性的 demo,或许开发者不方便装备网站 https 证书的时分,往往供给的都是依据 http 协议的拜访 url,假如父页面是依据 https 的话,在其嵌入 http 协议的 iframe 链接,就会报错而无法拜访。
那么,面对这样的场景,咱们该怎么去完成呢?
1 | 思路
其实顶层 workaround 的思路便是两个方向,怎么做,能够:
- 在 https 的 iframe 里支持 http 的拜访?
- 把 http 的拜访转化成 https 的?
第一个方向,调研了几天,各种搜索,问GPT,得到的结论是:不行,原因如下:
- 混合内容问题:当一个安全的 HTTPS 页面试图加载非安全的 HTTP 内容时,这种情况被称为“混合内容”。浏览器通常会阻挠这种行为,由于它降低了整个页面的安全性。
- 安全危险:HTTP 内容没有加密,易受中间人进犯。假如在 HTTPS 页面中加载 HTTP 内容,进犯者或许利用这个未加密的内容来进犯整个页面,比方经过注入恶意脚本。
- 隐私和完整性:HTTPS 旨在维护用户数据的隐私和完整性。混合内容使得 HTTPS 页面的这些保障部分失效,由于嵌入的 HTTP 内容不受相同的维护。
- 用户信赖:用户或许信赖一个安全的 HTTPS 页面,假如这个页面包括不安全的内容,这或许误导用户,使他们对整个页面的安全性有错误的了解。
调转方向,研究第二个思路。其实,此刻问题能够进一步细化:任意给定一个 http 的链接,怎么用 https 来拜访?
自然而然,面对和 url 相关的需求,首要想到的便是 nginx 署理(什么,想不到?!那就多看看烂笔头的文章:》)。大概思路如下:
- 建立一个 nginx 署理服务;
- 供给一个依据 https 的 url,nginx 接收到恳求 url;
- 编写 lua 脚本,完成对恳求 url 解析,生成原始的 http 恳求 url;
- 运用 proxy_pass 将 https 的恳求转发给 原始的 http 地址。
需求留意的是,这种计划需求有个前置条件,具有泛域名证书。泛域名证书要钱?来看看这篇文章,请求一个免费的~《网站要上 HTTPS 却没有 SSL/TLS 证书?| 教你一招搞定免费的(泛域名)SSL/TLS 证书》
2 | 实战
2.1 转化规则
要完成https url 转 http url,首要需求设置转化规则。咱们知道,url 是由 协议+域名+端口 组成的,比方:
能够看到,一个 url 里会包括字母、数字、符号等等,那么能够设置转化规则如下:
- 数字/字母 -> 数字/字母
- 符号 -> {符号英文},比方
. -> _dot_
,: -> _colon_
- 实在 url 转化后的字符串作为 base url 的二级子域名
假定 base url 为 abc.com,那么 http://192.168.0.1:6443 这个 http url 就能够转化为:
192_dot_168_dot_0_dot_1_colon_6443.abc.com
2.2 nginx 要害装备
首要,经过ngx.re.match找出二级子域名,
然后,将值赋给ngx.var.service,
接着,履行proxy办法,在proxy办法里,运用lua的string.gsub函数对字符串做替换操作,生成实在的拜访url,
最终,利用proxy_pass 将恳求转发出去。
这儿展现核心代码:
server {
listen 80;
location / {
set $service '';
set $type '';
rewrite_by_lua '
local host = ngx.var.host
local m = ngx.re.match(host, "(.+).abc.com")
ngx.var.service = m[1]
ngx.exec("@proxy")
';
}
location @proxy {
access_by_lua_block {
local req_service = ngx.var.service
local real_service = string.gsub(req_service, "_dot_", ".")
real_service = string.gsub(real_service, "_slash_", "/")
real_service = string.gsub(real_service, "_colon_", ":")
ngx.var.service = real_service
}
proxy_pass http://$service;
}
}
需求留意的是,这儿仅仅最核心的部分代码,还有一些必要的nginx装备(比方加头,支持ws协议等等),需求依据事务需求定制化去添加和修改。
以上。