在特定视图中可访问的变量称为locals
。Locals表示服务器端数据,这些数据可访问于您的视图——除非您使用视图引擎提供的特殊语法显式引用它们,否则locals实际上不会包含在编译后的HTML中。
<div>Logged in as <a><%= user.fullName %></a>.</div>
访问locals的表示法在不同的视图引擎之间有所不同。在EJS中,您使用特殊的模板标记(例如<%= someValue %>
)将locals包含在您的视图中。
EJS中有三种模板标签
<%= someValue %>
someValue
本地变量进行HTML转义,然后将其作为字符串包含。<%- someRawHTML %>
someRawHTML
本地变量,不进行转义。<% if (!loggedIn) { %> <a>注销</a> <% } %>
<% ... %>
内的JavaScript。if
/else
)和遍历数据(for
/each
)很有用。这是一个使用两个locals(user
和corndogs
)的视图(views/backOffice/profile.ejs
)示例
<div>
<h1><%= user.fullName %>'s first view</h1>
<h2>My corndog collection:</h2>
<ul>
<% for (let corndog of corndogs) { %>
<li><%= _.capitalize(corndog.name) %></li>
<% } %>
</ul>
</div>
您可能已经注意到另一个locals:
_
。默认情况下,Sails会自动将一些locals传递到您的视图中,其中之一是lodash(_
)。
如果您要传递到此视图的数据完全是静态的,则不一定需要控制器。相反,您可以像这样在config/routes.js
文件中硬编码视图及其locals
// ...
'get /profile': {
view: 'backOffice/profile',
locals: {
user: {
fullName: 'Frank',
emailAddress: '[email protected]'
},
corndogs: [
{ name: 'beef corndog' },
{ name: 'chicken corndog' },
{ name: 'soy corndog' }
]
}
},
// ...
但是,更有可能的是,此数据将是动态的。在这种情况下,我们需要使用控制器操作从我们的模型加载数据,然后使用res.view()方法将其传递给视图。
假设我们将我们的路由连接到我们其中一个控制器的操作(并且我们的模型已设置),我们可能会像这样发送我们的视图
// in api/controllers/UserController.js...
profile: function (req, res) {
// ...
return res.view('backOffice/profile', {
user: theUser,
corndogs: theUser.corndogCollection
});
},
// ...
exposeLocalsToBrowser
转义不受信任的数据通常希望将数据“引导”到页面上,以便在页面加载后立即通过Javascript访问,而不是必须在单独的AJAX或socket请求中获取数据。像Twitter和GitHub这样的网站在很大程度上依赖于这种方法,以优化页面加载时间并提供改进的用户体验。
从历史上看,这个问题通常是使用隐藏表单字段或手动编写代码来解决的,这些代码将服务器端locals直接注入到客户端脚本标签中。虽然有效,但当某些要引导的数据来自不受信任的来源时,这些技术可能会带来挑战,这些来源可能包含HTML标签和Javascript代码,旨在通过XSS攻击破坏您的应用程序。为了防止这种情况,Sails提供了一个内置的视图部分,称为exposeLocalsToBrowser
,您可以使用它安全地注入来自视图locals的数据以供客户端JavaScript访问。
要使用exposeLocalsToBrowser
,只需使用模板语言的非转义语法从视图中调用它即可。例如,使用默认的EJS视图引擎
<%- exposeLocalsToBrowser() %>
默认情况下,这会将您所有的视图locals公开为window.SAILS_LOCALS
全局变量。例如,如果您的操作代码包含
res.view('myView', {
someString: 'hello',
someNumber: 123,
someObject: { owl: 'hoot' },
someArray: [1, 'boot', true],
someBool: false
someXSS: '<script>alert("all your credit cards belong to me!!");</script>'
});
那么如上所示使用exposeLocalsToBrowser
将导致locals以安全的方式引导,这样window.SAILS_LOCALS.someArray
将包含数组[1, 'boot', true]
,而window.SAILS_LOCALS.someXSS
将包含字符串<script>alert("all your credit cards belong to me!!");</script>
,而不会导致该代码在页面上实际执行。
exposeLocalsToBrowser
函数有一个options
参数,可用于配置输出的数据及其方式。options
参数是一个字典,可以包含以下属性
属性 | 类型 | 默认值 | 详情 | |
---|---|---|---|---|
1 | keys | undefined |
要公开的locals的“白名单”。如果保留为未定义,则将公开所有locals。如果指定,则应为locals字典中属性名称的数组。例如,给定上面显示的res.view() 语句,设置keys: ['someString', 'someBool'] 将导致windows.SAILS_LOCALS 设置为{someString: 'hello', someBool: false} 。 |
|
2 | namespace | SAILS_LOCALS |
应将引导数据分配到的全局变量的名称。 | |
3 | dontUnescapeOnClient | false | 高级。不建议大多数应用程序使用。如果设置为true ,则任何为了避免XSS攻击而转义的字符串值在从客户端JS访问时仍然会被转义,而不是转换为原始值。例如,给定上面示例中的res.view() 语句,使用exposeLocalsToBrowser({dontUnescapeOnClient: true}) 将导致window.SAILS_LOCALS.someXSS 设置为<script>alert('hello!'); 。 |