我有一个网站,我正在从 Classic ASP 转换为 ASP.NET。旧网站允许用户编辑网站模板,为他们的网站部分创建自己的设计(想想 MySpace,只有 LESS 专业。)
我一直在绞尽脑汁想弄清楚如何使用 .NET 来做到这一点。我的网站通常使用母版页,但显然这不适用于最终用户。
我尝试将 HTML 模板加载为常规文本文件,并将其解析为“适合”内容占位符。它和听起来一样丑陋。
这里有一个通常被认为是最佳实践的东西,但我肯定找不到它。
有什么建议么?
我有一个网站,我正在从 Classic ASP 转换为 ASP.NET。旧网站允许用户编辑网站模板,为他们的网站部分创建自己的设计(想想 MySpace,只有 LESS 专业。)
我一直在绞尽脑汁想弄清楚如何使用 .NET 来做到这一点。我的网站通常使用母版页,但显然这不适用于最终用户。
我尝试将 HTML 模板加载为常规文本文件,并将其解析为“适合”内容占位符。它和听起来一样丑陋。
这里有一个通常被认为是最佳实践的东西,但我肯定找不到它。
有什么建议么?
您希望您的用户拥有多少控制权?
有几种方法可以实现这一点。我将简要总结一下我能想到的所有想法:
通过这种方法,您可以获得完全控制权,并将任何安全漏洞的风险降到最低。您可以将每个用户的 HTML 存储在某个数据库表中。该 HTML 将具有带有一些标记的预定义字段,例如使用{fieldName}
. 然后,您将使用一个简单的解析器来识别大括号并替换fieldName
为从Dictionary<String,String>
某个地方提取的字符串值。
如果您对字符串处理很聪明(即使用状态机解析器来查找花括号,将重建的字符串直接发送到输出或 StringBuilder 等,重要的是不使用String.Replace
),这种方法可能会很快。缺点是它不是一个真正的模板系统:没有提供循环结果集(假设你想允许),表达式评估,但它适用于简单的“将这个内容插入这个空间”类型的设计。
如果可以使用 ASP.NET,为什么还要构建自己的模板系统?好吧,如果您想构建一个快速的“n”脏报告系统,这种方法是最简单的,但它在安全性方面非常失败。不幸的是,由于 ASP.NET 的工作原理,您无法保护沙箱中 ASPX 文件中的任何<% %>
/代码或使用 CAS(我之前自己研究过:基于每个视图的 ASP.NET MVC 的代码访问安全性)。<script runat="server">
您不需要将实际的 ASPX 和 ASCX 文件存储在网站的文件系统中,您可以使用VirtualPathProvider
实现将文件存储在数据库中,但是让它正常工作可能有点痛苦(尤其是作为 ASP.NET运行时编译 ASPX 文件,因此如果用户修改了 ASPX 文件,您需要通知它)。您还需要注意,ASPX 加载与用户的请求路径相关联(除非您使用路由或 MVC),因此您最好使用 ASCX,这并不重要。
这是最痛苦的选择,它介于两者之间:您可以获得一流模板引擎的灵活性(循环、字段、必要时的评估),而无需打开应用程序以应对巨大的安全漏洞。缺点是你需要自己构建几乎所有东西。我不会在这里详细介绍。
您选择哪个选项取决于您的要求。MySpace 的系统更像是“换皮”而不是“模板化”,因为用户可以自由设置样式表并定义一些任意的通用 HTML,而不是直接修改他们页面的通用模板。
您可以在 ASP.NET 中轻松实现类似 MySpace 的系统,假设每个可换肤功能都作为Control
子类实现,只需扩展您的Render
方法以允许插入所述任意 HTML。添加自定义样式表也很容易:只需将其添加到<style type="text/css">
页面的<head>
.
当/如果您确实允许用户直接输入 HTML,我强烈建议您对其进行解析并过滤掉任何危险元素(例如<script>
、<style>
、<object>
等)。如果您想允许嵌入 YouTube 视频和相关视频,那么您应该分析<object>
元素以确保它们确实属于 YouTube 视频,提取视频 ID,然后从已知的受信任模板重新创建元素。任何自定义 HTML 都是“标签平衡”的,这一点很重要(您可以通过严格的 XML 解析器而不是更宽容的 HTML 解析器来验证这一点,因为无论如何 XHTML (技术上)是 HTML 的一个子集),这样任何自定义标记不会破坏页面。
玩得开心。