AngularJS使用trustAsHtml时如何防范XSS攻击?
嘿,这个问题问到点子上了——直接用trustAsHtml处理不可信的用户输入确实会埋下XSS隐患,尤其是像恶意用户名这种场景。别担心,有几个安全且靠谱的方法能解决这个问题:
1. 优先使用AngularJS的自动转义(最安全的方案)
AngularJS默认会对{{}}插值表达式里的内容自动转义特殊字符,所以其实你根本不需要用trustAsHtml来实现用户名加粗的需求。直接拆分模板就行:
比如把模板写成这样:
<strong>{{ username }}</strong> 刚刚对你的帖子执行了操作。
不管用户输入的是正常用户名还是alert('xss');这种恶意内容,AngularJS都会把它转成纯文本显示,不会执行任何脚本。这种方式完全规避了XSS风险,是首选方案。
2. 若需拼接HTML,用$sanitize服务过滤不安全内容
如果你确实需要动态拼接HTML内容(比如更复杂的通知格式),一定要用AngularJS官方提供的$sanitize服务,它会自动过滤掉所有不安全的HTML标签和脚本,只保留安全的内容。步骤如下:
第一步:引入依赖
首先确保你的项目中引入了angular-sanitize.js文件,然后在你的AngularJS模块中依赖ngSanitize:
angular.module('yourAppName', ['ngSanitize']);
第二步:在控制器中处理内容
用$sanitize处理拼接后的HTML内容,而不是直接用$sce.trustAsHtml:
app.controller('NotificationController', ['$scope', '$sanitize', function($scope, $sanitize) { // 假设这是从后端获取的用户名(可能包含恶意内容) const unsafeUsername = "alert('xss');"; // 用$sanitize过滤后拼接成安全的HTML $scope.safeNotification = $sanitize(`<strong>${unsafeUsername}</strong> 刚刚对你的帖子执行了操作。`); }]);
第三步:在模板中使用ng-bind-html
在模板里用ng-bind-html指令渲染处理后的内容:
<div ng-bind-html="safeNotification"></div>
这样$sanitize会把恶意脚本完全过滤掉,最终只会显示纯文本的用户名,不会触发XSS攻击。
3. 封装自定义过滤器(复用场景)
如果这个需求在多个地方用到,可以封装一个自定义过滤器,结合$sanitize来统一处理:
app.filter('safeBoldUsername', ['$sanitize', function($sanitize) { return function(username) { return $sanitize(`<strong>${username}</strong>`); }; }]);
然后在模板里直接使用过滤器:
<span ng-bind-html="username | safeBoldUsername"></span> 刚刚对你的帖子执行了操作。
重要提醒
永远不要用$sce.trustAsHtml处理来自用户输入的不可信内容!它会完全信任传入的HTML,跳过所有安全检查,这正是XSS攻击的入口。
内容的提问来源于stack exchange,提问作者Raz

