强制Backbone或Underscore总是逃避所有变量?

时间:2014-02-27 14:32:52

标签: javascript backbone.js xss

我是Backbone的新手,正在帮助维护应用。我想在Backbone的所有正常情况下都默认为逃避模型数据,以帮助避免默认的XSS攻击。

我知道我们可以使用

来做到这一点
<%- someModelAttribute %>

model.escape('attr')

在我们的应用中转义数据,但我想将其切换为

<%= someModelAttribute %>

model.get('attr')

也做了同样的事情....所以默认情况下,默认情况下会使用这些标记和方法的所有现有代码和未来代码进行转义。然后我想介绍另一种模型方法,例如&#34; model.getDataThatShouldBeSafeHtml&#34;在他们获取应包含HTML的数据时,让开发人员100%清楚。

所以我可以通过某种方式切换&#34;&lt;%=&#34;标签和&#34; model.get&#34;方法与它们的转义等价物相同?

我只是问,因为我以为这可能已经在某个地方完成,或者已经成为骨干的一部分,我想避免重建轮子!

3 个答案:

答案 0 :(得分:4)

我发现了一种简单的方法,因此默认情况下所有模板都会被转义。由于Backbone使用Underscore作为它的模板引擎,我搜索了一下,发现您可以使用_.templateSettings自定义下划线分隔符,描述为here on the Underscore site。请注意,如果您确保使用这些模板写出所有html,那么您将了解所有XSS。所以不要在一些简单的场景中跳过使用模板,在这些情况下也要使用它们来避免使用XSS!

您可以使用此小提琴进行测试: http://jsfiddle.net/vx0pw2n0/

所以我所做的就是这样做,因此默认情况下<%=<%-都用于显示转义数据。 evaluate标记<%仍然存在,可以使用print语句输出您想要的任何HTML。我还介绍了一个新标记<%cleanHtml,可用于输出HTML而不进行转义,而无需说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>

全球工作

要使全局工作,您可能必须将Underscore配置为模块,可以这样做:

实施为Backbone的依赖

配置Require.js模块

// 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 _;
});

答案 1 :(得分:2)

您可以扩展Backbone.Model以创建可重用的基类,为您执行此操作。像这样(未经测试):

BaseModel = Backbone.Model.extend({

    getSafeAttributes: function() {
        var safe = {};
        _.each(this.attributes, function(key, value) {
            safe[key] = _.escape(value);
        });
        return safe;
    }

});

我猜你的render函数看起来像

this.$el.html(this.template(this.model.attributes));

所以,而不是那样,你会写:

this.$el.html(this.template(this.model.getSafeAttributes()));

并确保您的模型扩展基类而不是Backbone.Model

修改backbone.jsunderscore.js以获得类似的结果是完全可以接受的,但它确实让升级成为一种痛苦,这就是我改为使用基类的原因。

答案 2 :(得分:0)

据我所知,骨干网取决于下划线提供的模板引擎。

How to use underscore.js as a template engine?

通过下划线,您可以将正则表达式模式更改为始终转义,但它不会调用模型的转义方法,因此您必须创建自己的模板引擎才能执行此操作...

例如,您可以从下划线分叉模板代码并以您自己的方式开发它并使用它代替_.template()