17370845950

在EJS模板中正确渲染CKEditor生成的HTML内容

本文详细介绍了在使用EJS模板引擎渲染CKEditor生成的富文本内容时,如何避免HTML标签被转义而显示为纯文本的问题。通过对比EJS的两种输出标签`

在使用富文本编辑器(如CKEditor)创建内容时,我们通常期望最终在网页上看到的是经过格式化的文本,而不是带有HTML标签的原始字符串。然而,当将这些HTML内容传递给视图引擎(如EJS)进行渲染时,如果不了解视图引擎的默认行为,可能会遇到HTML标签被转义(escaped)的问题,导致页面上直接显示

Lorem ipsum...

这样的纯文本。

问题根源:EJS的默认HTML转义行为

EJS(Embedded JavaScript)作为一种流行的模板引擎,其设计哲学之一是默认情况下提供安全的输出。这意味着,当你使用标准的语法来输出变量内容时,EJS会自动对内容中的HTML特殊字符进行转义。例如,会被转义为youjiankuohaophpcn,&会被转义为&等。这种机制有效地防止了跨站脚本攻击(XSS),因为恶意脚本不会被浏览器解析执行。

然而,对于从CKEditor等富文本编辑器中获取的、本身就包含合法HTML标签的内容,这种默认的转义行为就成了障碍。编辑器生成的HTML字符串,例如:

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae maxime dolore necessitatibus iste aliquid dolorum in nostrum repellat rerum atque?

在使用输出后,在浏览器中会变成:

zuojiankuohaophpcnpyoujiankuohaophpcnzuojiankuohaophpcnstrongyoujiankuohaophpcnLorem ipsumzuojiankuohaophpcn/strongyoujiankuohaophpcn dolor sit amet, consectetur adipisicing elit.zuojiankuohaophpcniyoujiankuohaophpcn Quae maximezuojiankuohaophpcn/iyoujiankuohaophpcn dolore necessitatibus iste aliquid dolorum in nostrum repellat rerum atque?zuojiankuohaophpcn/pyoujiankuohaophpcn

浏览器将这些转义后的字符视为普通文本,因此页面上会直接显示带有尖括号的原始HTML标签。

解决方案:使用EJS的非转义输出标签

EJS提供了一个专门用于输出未转义HTML内容的标签:。这个标签告诉EJS,将变量内容作为原始HTML直接插入到模板中,而无需进行任何转义处理。

因此,要正确渲染CKEditor生成的富文本内容,只需将EJS模板中的输出语法从更改为。

示例代码:

假设你的Node.js/Express应用在路由中将CKEditor提交的内容存储在postBody变量中,并将其传递给EJS模板:

// app.js (或相关路由文件)
app.get('/post/:id', (req, res) => {
    // 假设从数据库或其他地方获取到包含HTML的postContent
    const postContent = "

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae maxime dolore necessitatibus iste aliquid dolorum in nostrum repellat rerum atque?

"; res.render('post', { content: postContent }); });

在你的EJS模板文件(例如post.ejs)中,正确的写法应该是:




    
    
    文章详情
    


    
        

文章标题

<%- content %>

使用后,浏览器会正确解析并渲染postContent中的HTML标签,呈现出带有粗体、斜体等格式的富文本内容。

注意事项与安全考量

虽然解决了富文本内容的渲染问题,但使用它时必须格外小心,尤其当内容来源于用户输入时。直接输出未经处理的用户输入HTML,会带来严重的安全风险,主要是跨站脚本攻击(XSS)

恶意用户可能会在CKEditor中输入包含JavaScript代码的HTML,例如:

@@##@@

如果这些内容被直接用输出到页面,浏览器会执行这些恶意脚本,可能导致:

  • 窃取用户Cookie和会话信息。
  • 篡改网页内容。
  • 重定向用户到恶意网站。

安全最佳实践:

  1. 内容消毒(Sanitization): 在将用户提交的HTML内容保存到数据库之前,或在将其传递给EJS模板之前,务必进行严格的消毒处理。这意味着你需要使用一个可靠的HTML消毒库(例如dompurify for Node.js)来移除或过滤掉所有潜在的恶意标签和属性,只保留安全的HTML结构和样式。

    const createDOMPurify = require('dompurify');
    const { JSDOM } = require('jsdom');
    
    const window = new JSDOM('').window;
    const DOMPurify = createDOMPurify(window);
    
    // 在保存到数据库或渲染前
    const cleanHTML = DOMPurify.sanitize(userSubmittedHTML);
    // 然后将 cleanHTML 传递给 EJS 模板
    res.render('post', { content: cleanHTML });
  2. 权限控制: 仅允许受信任的用户(例如管理员)发布未经严格消毒的富文本内容。对于普通用户,即使使用CKEditor,也应该对其输入进行严格的消毒。

总结

在EJS模板中渲染CKEditor等富文本编辑器生成的HTML内容时,关键在于理解EJS的两种输出标签:

  • :默认行为,对内容进行HTML转义,适用于显示纯文本或防止XSS攻击。
  • :非转义输出,将内容作为原始HTML直接插入,适用于渲染已确认安全的富文本内容。

为了确保安全,当内容来源于用户输入时,务必在输出前对HTML内容进行严格的消毒处理,以防范潜在的XSS攻击。正确选择和使用EJS的输出标签,是构建功能完善且安全的Web应用的关键一步。