admin管理员组文章数量:1023794
I'm new to Backbone, and am helping maintain an app. I'd like to make the default in all normal situations for Backbone to be escaping model data, to help avoid XSS attacks by default.
I know we can do this using
<%- someModelAttribute %>
and
model.escape('attr')
to escape data in our app, but I'd like to switch it so
<%= someModelAttribute %>
and
model.get('attr')
did the same as well.... So by default, all existing code and future code that uses these tags and methods is escaped by default. Then I'd like to introduce another model method like "model.getDataThatShouldBeSafeHtml" to make it 100% clear to developers when they're getting data that should include HTML.
So is there some way for me to switch the "<%=" tag and the "model.get" methods to be the same as their escape equivalents?
I only ask as I thought this might've been done somewhere before, or already be part of backbone, and I want to avoid rebuilding the wheel!
I'm new to Backbone, and am helping maintain an app. I'd like to make the default in all normal situations for Backbone to be escaping model data, to help avoid XSS attacks by default.
I know we can do this using
<%- someModelAttribute %>
and
model.escape('attr')
to escape data in our app, but I'd like to switch it so
<%= someModelAttribute %>
and
model.get('attr')
did the same as well.... So by default, all existing code and future code that uses these tags and methods is escaped by default. Then I'd like to introduce another model method like "model.getDataThatShouldBeSafeHtml" to make it 100% clear to developers when they're getting data that should include HTML.
So is there some way for me to switch the "<%=" tag and the "model.get" methods to be the same as their escape equivalents?
I only ask as I thought this might've been done somewhere before, or already be part of backbone, and I want to avoid rebuilding the wheel!
Share Improve this question edited Mar 4, 2014 at 18:04 Brad Parks asked Feb 27, 2014 at 14:32 Brad ParksBrad Parks 72.6k70 gold badges289 silver badges367 bronze badges3 Answers
Reset to default 4I found an easy way to make it so all templates by default are escaped. Since Backbone uses Underscore for it's templating engine, I googled around and found that you can customize the underscore delimiters using _.templateSettings
, described here on the Underscore site. Note that if you make sure all of your html is written out using these templates, then you're covered for all XSS. So don't skip using templates in some simple scenarios, use them to avoid XSS in those cases as well!
You can test it out using this fiddle: http://jsfiddle/vx0pw2n0/
So all I did was make it so both <%=
and <%-
are used to display escaped data by default. The evaluate tag <%
still remains, and can be used to output whatever HTML you want using the print
statement. I also introduced a new tag, <%cleanHtml
that can be used to output HTML without it being escaped, and without needing to say print(someVariable)
<script type="text/javascript">
//
// This is the important part - The part that changes what underscore uses
// for template delimiters.
//
_.templateSettings =
{
escape: /<%[=-]([\s\S]+?)%>/g,
interpolate: /<%cleanHtml([\s\S]+?)cleanHtml%>/g,
evaluate: /<%([\s\S]+?)%>/g
};
// Test it out
var t = _.template($('#t').html());
var html = t({ title: '<b>pancakes</b>' });
$("#target").html(html);
console.log(html);
</script>
<!-- Sample Underscore Template showing different ways of using it -->
<script id="t" type="text/x-underscore">
<div><%= title %></div>
<div><%- title %></div>
<div><%safeHtmlOnly title safeHtmlOnly%></div>
<div><% print(title) %></div>
</script>
<div id="target"></div>
Making this work globally
To get this to work globally, you may have to configure Underscore as a module, which can be done like so:
Implement as a dependency on Backbone
Configure Require.js modules
// When you initially setup require.js, add a new module to configure underscore
// Make it a dependency of backbone, so it'll always be loaded whenever
// backbone is used.
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscoreConfig', 'underscore', 'jquery'],
exports: 'Backbone'
},
jquery: {
exports: 'jQuery'
}
}
});
underscoreConfig.js
define(['underscore'], function (_) {
'use strict';
_.templateSettings =
{
escape: /<%[=-]([\s\S]+?)%>/g,
interpolate: /<%cleanHtml([\s\S]+?)cleanHtml%>/g,
evaluate: /<%([\s\S]+?)%>/g
};
return _;
});
You could extend Backbone.Model
to create a reusable base class that does this for you. Something like this (untested):
BaseModel = Backbone.Model.extend({
getSafeAttributes: function() {
var safe = {};
_.each(this.attributes, function(key, value) {
safe[key] = _.escape(value);
});
return safe;
}
});
I'm guessing your render
functions look something like
this.$el.html(this.template(this.model.attributes));
So, instead of that, you'd write:
this.$el.html(this.template(this.model.getSafeAttributes()));
and just make sure your models extend the base class instead of Backbone.Model
.
It's perfectly acceptable to modify backbone.js
and underscore.js
to achieve a similar oute, but it does make it a pain to upgrade, which is why I'd go with the base class instead.
As far as I know backbone depends on the template engine provided by underscore.
How to use underscore.js as a template engine?
By underscore you can change the regex patterns to always escape, but it won't call the escape method of your model, so you have to create your own template engine to do that...
For example you can fork the templating code from underscore and develop it in your own way and use that instead of _.template()
.
I'm new to Backbone, and am helping maintain an app. I'd like to make the default in all normal situations for Backbone to be escaping model data, to help avoid XSS attacks by default.
I know we can do this using
<%- someModelAttribute %>
and
model.escape('attr')
to escape data in our app, but I'd like to switch it so
<%= someModelAttribute %>
and
model.get('attr')
did the same as well.... So by default, all existing code and future code that uses these tags and methods is escaped by default. Then I'd like to introduce another model method like "model.getDataThatShouldBeSafeHtml" to make it 100% clear to developers when they're getting data that should include HTML.
So is there some way for me to switch the "<%=" tag and the "model.get" methods to be the same as their escape equivalents?
I only ask as I thought this might've been done somewhere before, or already be part of backbone, and I want to avoid rebuilding the wheel!
I'm new to Backbone, and am helping maintain an app. I'd like to make the default in all normal situations for Backbone to be escaping model data, to help avoid XSS attacks by default.
I know we can do this using
<%- someModelAttribute %>
and
model.escape('attr')
to escape data in our app, but I'd like to switch it so
<%= someModelAttribute %>
and
model.get('attr')
did the same as well.... So by default, all existing code and future code that uses these tags and methods is escaped by default. Then I'd like to introduce another model method like "model.getDataThatShouldBeSafeHtml" to make it 100% clear to developers when they're getting data that should include HTML.
So is there some way for me to switch the "<%=" tag and the "model.get" methods to be the same as their escape equivalents?
I only ask as I thought this might've been done somewhere before, or already be part of backbone, and I want to avoid rebuilding the wheel!
Share Improve this question edited Mar 4, 2014 at 18:04 Brad Parks asked Feb 27, 2014 at 14:32 Brad ParksBrad Parks 72.6k70 gold badges289 silver badges367 bronze badges3 Answers
Reset to default 4I found an easy way to make it so all templates by default are escaped. Since Backbone uses Underscore for it's templating engine, I googled around and found that you can customize the underscore delimiters using _.templateSettings
, described here on the Underscore site. Note that if you make sure all of your html is written out using these templates, then you're covered for all XSS. So don't skip using templates in some simple scenarios, use them to avoid XSS in those cases as well!
You can test it out using this fiddle: http://jsfiddle/vx0pw2n0/
So all I did was make it so both <%=
and <%-
are used to display escaped data by default. The evaluate tag <%
still remains, and can be used to output whatever HTML you want using the print
statement. I also introduced a new tag, <%cleanHtml
that can be used to output HTML without it being escaped, and without needing to say print(someVariable)
<script type="text/javascript">
//
// This is the important part - The part that changes what underscore uses
// for template delimiters.
//
_.templateSettings =
{
escape: /<%[=-]([\s\S]+?)%>/g,
interpolate: /<%cleanHtml([\s\S]+?)cleanHtml%>/g,
evaluate: /<%([\s\S]+?)%>/g
};
// Test it out
var t = _.template($('#t').html());
var html = t({ title: '<b>pancakes</b>' });
$("#target").html(html);
console.log(html);
</script>
<!-- Sample Underscore Template showing different ways of using it -->
<script id="t" type="text/x-underscore">
<div><%= title %></div>
<div><%- title %></div>
<div><%safeHtmlOnly title safeHtmlOnly%></div>
<div><% print(title) %></div>
</script>
<div id="target"></div>
Making this work globally
To get this to work globally, you may have to configure Underscore as a module, which can be done like so:
Implement as a dependency on Backbone
Configure Require.js modules
// When you initially setup require.js, add a new module to configure underscore
// Make it a dependency of backbone, so it'll always be loaded whenever
// backbone is used.
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscoreConfig', 'underscore', 'jquery'],
exports: 'Backbone'
},
jquery: {
exports: 'jQuery'
}
}
});
underscoreConfig.js
define(['underscore'], function (_) {
'use strict';
_.templateSettings =
{
escape: /<%[=-]([\s\S]+?)%>/g,
interpolate: /<%cleanHtml([\s\S]+?)cleanHtml%>/g,
evaluate: /<%([\s\S]+?)%>/g
};
return _;
});
You could extend Backbone.Model
to create a reusable base class that does this for you. Something like this (untested):
BaseModel = Backbone.Model.extend({
getSafeAttributes: function() {
var safe = {};
_.each(this.attributes, function(key, value) {
safe[key] = _.escape(value);
});
return safe;
}
});
I'm guessing your render
functions look something like
this.$el.html(this.template(this.model.attributes));
So, instead of that, you'd write:
this.$el.html(this.template(this.model.getSafeAttributes()));
and just make sure your models extend the base class instead of Backbone.Model
.
It's perfectly acceptable to modify backbone.js
and underscore.js
to achieve a similar oute, but it does make it a pain to upgrade, which is why I'd go with the base class instead.
As far as I know backbone depends on the template engine provided by underscore.
How to use underscore.js as a template engine?
By underscore you can change the regex patterns to always escape, but it won't call the escape method of your model, so you have to create your own template engine to do that...
For example you can fork the templating code from underscore and develop it in your own way and use that instead of _.template()
.
本文标签: javascriptForce Backbone or Underscore to always escape all variablesStack Overflow
版权声明:本文标题:javascript - Force Backbone or Underscore to always escape all variables? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745535131a2154926.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论