如何在 https 的 iframe 里访问 http 页面? | nginx应用实战-3

好记性不如 烂笔头,趁热记录下,给未来的自己

0 | 前言

项目需求永远是学习技术最好的动力

项目中,有这样一个业务场景,作为一个平台,可以部署用户写的各种应用,比如gradio应用,streamlit应用,也可以嵌入外部网站的url,这些应用在平台上通过嵌入 iframe 去展示。

然后,针对外部网站,有很多临时性的 demo,或者开发者不方便配置网站 https 证书的时候,往往提供的都是基于 http 协议的访问 url,如果父页面是基于 https 的话,在其嵌入 http 协议的 iframe 链接,就会报错而无法访问。

那么,面对这样的场景,我们该如何去实现呢?

1 | 思路

其实顶层 workaround 的思路就是两个方向,怎么做,可以:

  1. 在 https 的 iframe 里支持 http 的访问?
  2. 把 http 的访问转换成 https 的?

第一个方向,调研了几天,各种搜索,问GPT,得到的结论是:不行,原因如下:

  1. 混合内容问题:当一个安全的 HTTPS 页面试图加载非安全的 HTTP 内容时,这种情况被称为"混合内容"。浏览器通常会阻止这种行为,因为它降低了整个页面的安全性。
  2. 安全风险:HTTP 内容没有加密,易受中间人攻击。如果在 HTTPS 页面中加载 HTTP 内容,攻击者可能利用这个未加密的内容来攻击整个页面,比如通过注入恶意脚本。
  3. 隐私和完整性:HTTPS 旨在保护用户数据的隐私和完整性。混合内容使得 HTTPS 页面的这些保障部分失效,因为嵌入的 HTTP 内容不受同样的保护。
  4. 用户信任:用户可能信任一个安全的 HTTPS 页面,如果这个页面包含不安全的内容,这可能误导用户,使他们对整个页面的安全性有错误的理解。

调转方向,研究第二个思路。其实,此时问题可以进一步细化:任意给定一个 http 的链接,如何用 https 来访问?

自然而然,面对和 url 相关的需求,首先想到的就是 nginx 代理(什么,想不到?!那就多看看烂笔头的文章:》)。大概思路如下:

  1. 搭建一个 nginx 代理服务;
  2. 提供一个基于 https 的 url,nginx 接收到请求 url;
  3. 编写 lua 脚本,实现对请求 url 解析,生成原始的 http 请求 url;
  4. 使用 proxy_pass 将 https 的请求转发给 原始的 http 地址。

需要注意的是,这种方案需要有个前置条件,具备泛域名证书。泛域名证书要钱?来看看这篇文章,申请一个免费的~《网站要上 HTTPS 却没有 SSL/TLS 证书?| 教你一招搞定免费的(泛域名)SSL/TLS 证书》

2 | 实战

2.1 转换规则

要实现https url 转 http url,首先需要设置转换规则。我们知道,url 是由 协议+域名+端口 组成的,比如:

可以看到,一个 url 里会包含字母、数字、符号等等,那么可以设置转换规则如下:

  1. 数字/字母 -> 数字/字母
  2. 符号 -> {符号英文} ,比如 . -> _dot_, : -> _colon_
  3. 真实 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 将请求转发出去。

这里展示核心代码:

ini 复制代码
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协议等等),需要根据业务需求定制化去增加和修改。

以上。

相关推荐
计算机学姐2 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
JustinNeil2 小时前
简化Java对象转换:高效实现大对象的Entity、VO、DTO互转与代码优化
后端
青灯文案12 小时前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
微尘83 小时前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
计算机学姐3 小时前
基于PHP的电脑线上销售系统
开发语言·vscode·后端·mysql·编辑器·php·phpstorm
BLEACH-heiqiyihu4 小时前
红帽9中nginx-源码编译php
运维·nginx·php
码拉松4 小时前
千万不要错过,优惠券设计与思考初探
后端·面试·架构
白总Server5 小时前
MongoDB解说
开发语言·数据库·后端·mongodb·golang·rust·php
计算机学姐5 小时前
基于python+django+vue的家居全屋定制系统
开发语言·vue.js·后端·python·django·numpy·web3.py
这个需求建议不做5 小时前
vue3打包配置 vite、router、nginx配置
前端·nginx·vue