【问题标题】:Render and serve HTML file with CSS/JS from server disk to Client Browser使用 CSS/JS 从服务器磁盘渲染和提供 HTML 文件到客户端浏览器
【发布时间】:2020-07-20 20:08:44
【问题描述】:

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

应用程序

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

约束

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

技术细节

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

当前状态

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

  2. 正在运行: react js web 应用程序已构建,dist 文件托管在 IIS 服务器中,也可以毫无问题地访问它。

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

我坚持的功能

  1. 目标文件适用于不同的用户。因此,这必须在通过 API 请求进行验证后提供。
  2. 当前设置是这样的,当用户单击 react 应用程序中的链接时,它会进行 REST Api 调用,该调用由后端 dotnet 核心应用程序处理(可能有其他更好的方法将 html 文件提供给前端网络应用程序)。
  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 和链接的 css,客户端浏览器无法识别 js。下图显示了问题。 js和css也在同一个api端点搜索。

问题:

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

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

我只需要找到一种方法来验证用户,然后为他提供一个完全呈现的 html 页面以在他的浏览器中查看(这样解释听起来很容易) 任何帮助或方向/建议表示赞赏。

【问题讨论】:

  • the problem is that since I have put the files inside a static folder (configured in startup) users can easily change the URL and access other files present there 您说用户可以轻松访问存储在该文件夹中的其他文件,用户如何知道您的Web服务器上的这些文件信息,例如文件名,文件扩展名等?
  • 因为转换后的页面(由 Potree 转换器生成)具有项目文件名。任何有权访问该项目的用户都可以轻松猜出里面的模型名称。假设我们有一个模型“BuildingABC”,那么转换后的 html 页面将是“BuildingABC.html”,对于每个建筑物,我们遵循一组ISO 标准名称。因此,在建筑物上工作的人很容易猜到。

标签: html reactjs asp.net-core asp.net-web-api react-admin


【解决方案1】:

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

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

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

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

  1. React JS Web 应用:作为前端工作(我们称之为应用 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),在标题中添加标签以包含 url_guid 并放置它在一个公共目录中。

  2. 我们将 target_file_GUID 添加到我们的 Mysql 数据库表的列中,该列也有一个列来存储文件的实际名称。

解决方案

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

结论 我很抱歉写了很长的回复并且没有太多代码。整个设置和想法需要更多时间来构思(仍然可能有更好的方法来处理它。我不知道)。

这里的主要成就是

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多