使用 CSS/JS 从服务器磁盘到客户端浏览器呈现并提供 HTML 文件

Render and serve HTML file with CSS/JS from server disk to Client Browser

我遇到了一个问题,简单来说,就是找到一种方法来安全地呈现和提供 HTML 文件(以及 CSS、JS)从服务器中的本地磁盘到客户端浏览器中的 Web 应用程序 运行。

应用

  1. 前端 Web 应用程序是使用 React JS(准确地说是 react-admin)创建的。
  2. 处理 Rest API 请求的后端是使用 Net core 3.1
  3. 设置的
  4. 这两个应用程序都托管在 Windows 服务器的 IIS 中(作为 IIS 中默认网站内的应用程序服务)。

约束条件

  1. 应用程序的托管只能在 windows 服务器的 IIS 内部进行。 (也欢迎其他选项)
  2. 后端/前端可以是我们想要的任何语言。 (最好是 dot net core,因为我在过去 10 年一直使用 C#)

技术细节

我正在开发一个托管点云查看器的解决方案(Potree,一个使用 three-js 开发的开源项目)。这是一个独立的过程。 Potree 提供了一个基于桌面的 C++ 转换器,它将输入转换为网页(使用 html、css、js)(让我们将其称为目标文件 ).我们可以在任何服务器上托管此网页以供外部各方查看。

当前状态

  1. 工作:目标文件作为应用程序托管在 IIS 服务器中,可以毫无问题地访问它。 (图像可以在下面看到)。

  2. 工作: React js 网络应用程序已构建,dist 文件托管在 IIS 服务器中,也可以毫无问题地访问它。

以上两个步骤确认构建的应用程序运行良好,因为它们可以单独托管,也可以从其他计算机访问。

我坚持使用的功能

  1. 目标文件适用于不同的用户。因此,必须在通过 API 请求验证后提供服务。
  2. 当前设置是这样的,当用户在 React 应用程序中单击 link 时,它会进行 REST Api 调用,由后端 dotnet 核心应用程序处理(可能有其他更好的将 html 文件提供给前端 Web 应用程序的方法)。
  3. 我尝试了几种方法来提供 HTML 文件。 选项 1:使用 StaticFiles(在启动时)。我正在尝试从本地读取 html 文件,然后使用 @Html.Raw(Model.SomePropertyName)

    在 noidea.cshtml 文件中渲染它
        // GET: /<controller>/
    public IActionResult noidea()
    {
        try
        {
            var newmodel = new noideaModel();
            var file = System.IO.File.ReadAllLines("./acl-i/acl-i.html");
            newmodel._html = string.Join("", file);
            return View(newmodel);
    
            //return View();
        }
        catch (Exception)
        {
            throw;
        }
    }
    

    }

这个选项部分工作正常,但问题是因为我将文件放在静态文件夹中(在启动时配置)用户可以轻松更改 URL 并访问那里的其他文件。

因此,我尝试使用选项 2,即只从本地磁盘读取 html 文件的内容并将其作为内容结果提供。:

        [AllowAnonymous]
    [HttpGet, Route("viewer")]
    public IActionResult getViewer()
    {
        //For serving single static html file.
        var file = System.IO.File.ReadAllLines("./acl-i/acl-i.html");
        var item = string.Join("", file);

        return new ContentResult
        {
            ContentType = "text/html",
            StatusCode = (int)StatusCodes.Status200OK,
            Content = item
        };
    }

这里的成功点是,我能够正确验证并且用户无法更改 URL,因为 api 端点提供文件。 问题是我只提供 HTMl 和 linked css,客户端浏览器无法识别 js。下图显示了这个问题。 js和CSS也在同一个api端点被搜索

问题:

我是 React js 和 Web 前端开发的新手。我主要使用 Xamarin,C#/WPF/XML 用于桌面应用程序,并为 CRUD 应用程序开发 Web API 端点。所以,我完全被困在这里。不知道如何解决这个问题。

  1. 我正在寻找解决当前问题的方法。
  2. 或者找到一个优雅简单的方法来解决这个问题(我也看到了一些 express js 和 react js 的例子,但不清楚,我也是新手)。

我只需要找到一种方法来验证用户身份,然后为他提供一个完全呈现的 html 页面以在他的浏览器中查看(这听起来很容易以这种方式解释)任何帮助或指导/建议都将不胜感激。

我尝试了不同的方法来解决这个问题。最后,我找到了解决方案。 (可能不是最好的,但可能对也有类似问题的人有帮助)。

工作流程: 现在,我们每周都会从外部分包商那里收到几个构建的网页。我们的分包商使用 Potree Converter 将他们的点云数据转换为网页(其中有几个 html、js、css)压缩成大约 2-3 GB 的文件(由于点云的大小数据)。不可能一次性将所有文件下载到客户端浏览器。这是由 potree 网页本身处理的。根据用户浏览,html 页面抓取部分数据并频繁发送。但是,我们不必担心它,因为它完全由 Potree 开发团队管理(感谢维也纳工业大学计算机图形与算法研究所)

因此,我们无法对从分包商那里收到的 html 网站做很多事情。我们的工作是托管并为利益相关者提供安全访问。

应用程序: 最初我开发了两个应用程序,还有一个从 Potree 转换器转换的 html 页面。

  1. React JS 网络应用程序:用作前端(让我们调用应用程序 1
  2. dot net core 3.1 后端:用于处理 API 请求。 (让我们调用 App 2

此项目托管在 IIS 中。因此,我创建了一个新站点(运行 在防火墙后面的不同端口上并且不暴露给外部各方)。我们称其为 目标站点

通过 IIS 反向代理设置

  1. 我们在 IIS 中(通过 ARR)为所有传入请求设置了一个反向代理。
  2. IIS 将过滤在 URL 中具有特定字符串的传入 URL。 (例如, /5506f977-7463-4f85-86ff-7ca63bac34fa/ ,假设 url_guid)。
  3. URL 重写将改变这一点并直接到目标站点(运行 在防火墙后面的不同端口上)

**目标文件设置**

  1. 每次我们从分包商那里收到新的目标页面(转换后的 zip 文件)时,我们都会获取 index.html 文件,用 GUID (target_file_GUID) 重命名它,添加一个标记到 header 以包含 url_guid 并将其放在公共目录中。

  2. 我们将 target_file_GUID 添加到我们的 Mysql 数据库 table 的列中,其中还有一个列用于存储文件的实际名称。

解决方案

  1. 我们从应用程序 1 向应用程序 2 发送请求(在 header 秒内使用 JWT 身份验证和所需的 HTML 文件(或点云模型))。
  2. 验证后,我们从MYSQL
  3. 中获取相应html文件的guid名称
  4. 然后从公共目录中获取此特定文件并发送到浏览器。
  5. 在这一点上,浏览器 URL 仍然没有改变并且包含相同的 URL 用于访问 API 控制器。
  6. 加载 Html 文件时,它还会尝试加载 html 中提到的 CSS 所需的 JS 文件。诀窍就发生在这里。由于我们指定了标签,新的 url 请求被发送到服务器,被 IIS 拦截并重写到内部服务器。 (此时客户端浏览器中的URL仍然没有因为服务端Rewrite而改变)
  7. 客户端浏览器收到 JS,CSS 文件(但客户端浏览器中仍然 URL 并且请求 headers 没有显示实际 URL ).

结论 我为写了一个很长的回复而没有太多代码而道歉。整个设置和想法花了更多的时间来构思(可能还有更好的方法来处理它。我不知道)。

这里的主要成就是

  1. 在将用户引导至不同 URL 之前授权用户。
  2. URL Rewrite 不向客户端浏览器显示原始 url
  3. 原始目标站点仍受防火墙保护
  4. html 的原始文件名被 GUID 替换(用户很难猜到)并且这个 html guid 名称通过 windows 服务重复更改每周控制台应用程序。 (假设我们总共有 1000 个文件。名称每周都会更改以确保其安全和自信)。
  5. 用户无法直接访问 html 文件(即使他知道文件的名称。因为这仅在身份验证后通过 App 2 提供)

或多或少,我们认为在这一点上已经足够安全,可以继续进行下去了。如果其他人面临类似问题并取得了不同的解决方案,请分享。