Запуск скриптов в доверенном HTML с Angular 2
Что у меня есть
Я создаю приложение для личного блога с Angular 2. У меня есть записи в блоге в файле JSON, который подается с моего сервера.
// Single post route
apiRouter.route("/post/:id")
// Get a specific post
.get((req: express.Request, res: express.Response) => {
let post = blogData.posts.find(post => post.date === Number(req.params.id));
res.json(post);
})
);
Отдельные записи в файле данных блога JSON выглядят так:
"posts": [
{
"title": "Some Post's Title",
"body": "Some post's body.",
"date": 1481582451092,
"headerImageName": ""
},
{ ... }, ...
]
В моем веб-приложении я хочу иметь один компонент машинописного компонента "Запись блога", который отображает отдельный пост, когда посетитель находится на маршруте, который сопоставляется с одним постом.
Я определил простой класс данных поста, как это:
export class PostData {
body: string;
date: number;
imageFileName: string;
title: string;
}
При отображении тела сообщения я пропускаю его через эту трубу:
@Pipe({
name: "trustPipe"
})
export class TrustPipe implements PipeTransform {
constructor(@Inject(DomSanitizer) private sanitizer: DomSanitizer) { }
transform(html: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
}
Чтобы отобразить его, я написал следующий компонент:
import { TrustPipe } from "./trust.pipe";
@Component({
selector: "active-component",
template: `
<div class="card">
<div *ngIf="post">
<div class="card-title">
<span>{{ post.title }}</span>
</div>
<div [innerHTML]="post.body | trustPipe"></div>
</div>
</div>`,
styleUrls: ["styles/post.component.css", "styles/card.css"]
})
export class PostComponent implements OnInit {
// Post is a superclass to PostData, it just provides
// some helper functions on the base class, such as truncation
// and a means of formatting dates
post: Post;
constructor(
@Inject(BlogService) private blogService: BlogService,
@Inject(ActivatedRoute) private activatedRoute: ActivatedRoute
) { }
ngOnInit(): void {
this.activatedRoute.params.forEach((params: Params) => {
const id: number = +params["id"];
this.blogService
.getPost(id)
.then(data => this.post = new Post(data));
});
}
}
Что все это делает?
При этом важно отметить, что у меня есть некоторая вариантная строка (JSON для тела сообщения), представляющая раздел HTML, который я хотел бы вставить как дочерний элемент для некоторого элемента DOM. Для этого я использовал [innerHTML]
атрибут и написал угловую трубу, которая использует bypassSecurityTrustHtml
за доверие к строке как к безопасному HTML.
Что просходит?
Теги скрипта не выполняются. Скажем, я написал пост в блоге, в котором есть что-то встроенное - в моем случае это скорее всего Github Gist, фотография из Instagram или альбом фотографий Google. Я обнаружил, что это правда - теги script не выполняются - и средство использования Javascript для его обхода, но я хочу знать, есть ли в angular способ вставки HTML, как я пытаюсь. Я видел использование ComponentFactory
но я не знаю, хочу ли я этого. Я предполагаю, что это также остановит меня от использования routerLinks
в телах моего поста. Я мог бы написать дочерний компонент для тела сообщения, но тогда как мне динамически поменять шаблоны?
Вопросы
а) Почему Angular останавливает запуск скриптов?
б) Есть ли другие способы заставить скрипты работать?
в) Должен ли я использовать другой шаблон дизайна для этого - например, показывать сообщения в формате HTML?
1 ответ
А) Безопасность и, в частности, защита от XSS - https://angular.io/docs/ts/latest/guide/security.html
б) Да, но будьте очень осторожны - https://angular.io/docs/ts/latest/guide/security.html
Вы пытались обойти API безопасности в вашем компоненте вместо трубы? Кроме того, какой контекст безопасности вы используете?
в) Можете ли вы проанализировать сообщение в блоге и сохранить его в безопасном формате, или вы действительно хотите разрешить запуск любых js на вашем сайте?