特定のビューで使用できる変数をlocals
(ローカル変数)と呼びます。ローカル変数は、ビューで使用可能なサーバーサイドのデータを表します。ローカル変数は、ビューエンジンが提供する特別な構文を使用して明示的に参照しない限り、コンパイルされたHTMLには実際には含まれません。
<div>Logged in as <a><%= user.fullName %></a>.</div>
ローカル変数へのアクセス方法は、ビューエンジンによって異なります。EJSでは、特別なテンプレートマークアップ(例:<%= someValue %>
)を使用して、ビューにローカル変数を組み込みます。
EJSには3種類のテンプレートタグがあります
<%= someValue %>
someValue
をHTMLエスケープしてから、文字列として含めます。<%- someRawHTML %>
someRawHTML
をエスケープせずにそのまま含めます。<% if (!loggedIn) { %> <a>ログアウト</a> <% } %>
<% ... %>
内のJavaScriptを実行します。if
/else
)やデータのループ処理(for
/each
)に役立ちます。2つのローカル変数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>
別のローカル変数
_
に気づかれたかもしれません。デフォルトでは、Sailsはいくつかのローカル変数を自動的にビューに渡します。その1つがlodash(_
)です。
このビューに渡すデータが完全に静的な場合、コントローラーは必ずしも必要ありません。代わりに、ビューとそのローカル変数をconfig/routes.js
ファイルにハードコーディングすることができます。
// ...
'get /profile': {
view: 'backOffice/profile',
locals: {
user: {
fullName: 'Frank',
emailAddress: '[email protected]'
},
corndogs: [
{ name: 'beef corndog' },
{ name: 'chicken corndog' },
{ name: 'soy corndog' }
]
}
},
// ...
しかし、より可能性が高いのは、このデータが動的であることです。このシナリオでは、コントローラーアクションを使用してモデルからデータを読み込み、res.view()メソッドを使用してビューに渡す必要があります。
ルートをコントローラーのアクションの1つに接続し(そしてモデルが設定されていると仮定して)、ビューを次のように送信するかもしれません。
// 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などのサイトは、ページの読み込み時間を最適化し、ユーザーエクスペリエンスを向上させるために、このアプローチに大きく依存しています。
従来、この問題は、非表示のフォームフィールドを使用するか、サーバーサイドのローカル変数をクライアントサイドのスクリプトタグに直接挿入するコードを手動で作成することで解決されていました。効果的ですが、ブートストラップするデータの一部が、HTMLタグとJavascriptコードを含み、XSS攻撃によってアプリケーションを侵害しようとする信頼できないソースからのものである場合、これらの手法には課題が生じる可能性があります。このような状況を防ぐために、Sailsは、クライアントサイドのJavaScriptからアクセスするために、ビューのローカル変数からデータを安全に挿入するために使用できる、exposeLocalsToBrowser
という組み込みビューパーシャルを提供します。
exposeLocalsToBrowser
を使用するには、テンプレート言語のエスケープしない構文を使用してビュー内で呼び出すだけです。たとえば、デフォルトのEJSビューエンジンを使用する場合
<%- exposeLocalsToBrowser() %>
デフォルトでは、すべてのビューローカル変数を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
を使用すると、ローカル変数は安全にブートストラップされ、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 |
公開するローカル変数の「ホワイトリスト」。undefinedのままにすると、すべてのローカル変数が公開されます。指定する場合は、ローカル変数辞書のプロパティ名の配列にする必要があります。たとえば、上記で示した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!'); に設定されます。 |