如何通过AngularJs避免在JavaScript中添加前缀"unsafe"?

4
我是一个有用的助手,可以为您翻译文本。
我尝试在我的网站上添加书签按钮,并通过生成控制器中的链接来实现。
模板部分:
    <a id="bookmarklet"
       class="bookmarklet"
       onclick="alert('Drag and drop me to the bookmarks bar');return false;"
       href="{{getCode()}}">
      + Add
    </a>

控制器部分:

$scope.getCode = function () {
  var code = 'javascript:(function(){s=document.createElement(\'SCRIPT\');s.type=\'text/javascript\';' +
    's.src=\'http://localhost:9000/scripts/bookmarklet/bookmarklet.js?x=' + ($scope.user.id) + '\';' +
    'document.getElementsByTagName(\'head\')[0].appendChild(s);document.sc_srvurl=\'http://localhost:8080\'})();'  ;
  return code;
};

但我在编译后得到以下结果:

<a class="bookmarklet" href="unsafe:javascript:(function(){s=document.createElement('SCRIPT');s.type='text/javascript';s.src='http://localhost:9000/scripts/bookmarklet/bookmarklet.js?x=5517325d40c37bc2bfe20db6';document.getElementsByTagName('head')[0].appendChild(s);document.sc_srvurl='http://localhost:8080'})();">
              + Add
            </a>

链接以 "unsafe" 开头,我不知道如何告诉 Angular 信任这个链接。这个答案 - Angular changes urls to "unsafe:" in extension page 建议将协议添加到白名单中。我不想禁用 $sce 或将 "javascript" 添加到白名单协议中,因为我认为这是不安全的。我能否通过使用 $sce 来告诉 AngularJS 避免添加前缀 "unsafe"?不幸的是,对于我来说文档并不清晰,并且 $sce.trustAsJs(code)没有帮助我。注意:Angular 版本为 1.4.1。

在https://dev59.com/fWUo5IYBdhLWcg3w_DpK中的解决方案是将协议添加到白名单中,而我在我的情况下关注安全性。 - Ivan Kaplin
我认为你没有其他选择。而且你不会添加“javascript”,你应该将“chrome-extension”添加到白名单中。 - Matthew Green
这确实是一个有效的关注点。我能想到的另一种替代方法是创建一个指令,并在那里设置href属性的值(通过直接操作指令的DOM元素来完成)。对于您的用例,这种方法可行吗? - plamut
@plamut,我不清楚指令的解决方法如何帮助。我想知道是否有直接的方法告诉Angular信任这个URL? - Ivan Kaplin
@IvanKaplin 指令直接与DOM元素交互,设置属性值可以规避Angular的安全机制和“有效”链接策略。因此,您可以将href属性设置为任何您想要的内容,而无需将任何内容添加到$compileProvider的白名单中。 - plamut
1个回答

2
尝试编写自定义指令来绕过限制:
var app = angular.module('myApp', []);

app.directive('bookmarklet', function () {
    return {
        restrict: 'A',
        scope: {},
        link: function($scope, element, attrs) {
            if (element[0].tagName !== 'A') {
                return;  // simply do nothing (or raise an error)
            }
            element[0].href = 'javascript:alert("It works in 1.4.1, too!")';
        }
    };
 });

使用方法:

<div ng-app="myApp">
    <a href="#foo" bookmarklet>click me</a>
</div>

我还创建了一个fiddle演示来测试它:http://jsfiddle.net/t0acdxcL/1/

我现在已经修复了演示链接。 - plamut
谢谢!我看到你的代码可以正常运行,而且没有不安全的 'javascript:alert("It works!")'。但是我在我的项目中尝试了一下,仍然有不安全的 href="unsafe:javascript:alert('It works!')"。想知道这两者之间的区别是什么。 - Ivan Kaplin
我已将Angular依赖项更新为1.4.1并进行了复制。请参见此fiddle - http://jsfiddle.net/ikaplin/8rm57bwf/2/ - Ivan Kaplin
我会补充问题,Angular 版本是 1.4.1。 - Ivan Kaplin
1
我更新了我的答案和演示,现在它也可以在1.4.1中工作。似乎attrs.$set(...)的行为在某个时候发生了变化,但是绕过这一点很容易。直接在元素上设置属性值就可以了,即element [0] .href = ... - plamut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接