Merge remote-tracking branch 'origin/master'

# Conflicts:
#	public/_data.json
#	public/docs/ts/latest/_data.json
#	public/docs/ts/latest/guide/router.jade
#	public/docs/ts/latest/guide/security.jade
#	public/docs/ts/latest/guide/template-syntax.jade
#	public/news.jade
#	public/resources/_data.json
#	public/resources/index.ejs
#	public/resources/js/controllers/resources-controller.js
This commit is contained in:
Zhicheng Wang 2016-07-01 08:38:54 +08:00
commit 0dd2932a2e
27 changed files with 379 additions and 242 deletions

View File

@ -671,9 +671,9 @@ gulp.task('lint', function() {
'!./public/docs/_examples/_protractor/**/*',
'!./public/docs/_examples/**/typings/**/*',
'!./public/docs/_examples/**/typings-ng1/**/*',
'!./public/docs/_examples/**/build/**/*',
// temporary until codelyzer is fixed mgechev/codelyzer#60
'!./public/docs/_examples/animations/ts/app/hero.service.ts'
])
.pipe(tslint({
rulesDirectory: ['node_modules/codelyzer'],

View File

@ -477,6 +477,13 @@
"twitter": "rexebin",
"bio": "Rex is a full-stack developer. He maintains the Angular.cn website with his old pal Ralph Wang and he plays a key role in bridging between the Chinese Angular community and the world-wide community. He loves playing with flashy new technologies and enjoys the challenge of mastering new skills. His biggest challenge to date is figuring out how to sooth a crying 4-month-old baby.",
"type": "Community"
},
"ralph": {
"name": "Ralph Wang",
"picture": "/resources/images/bios/ralph.jpg",
"twitter": "ralph_wang_gde",
"bio": "Ralph(Zhicheng Wang) is a senior consultant at ThoughWorks and also a GDE. He is a technology enthusiast and he is a passionate advocate of “Simplicity, Professionalism and Sharing”. In his eighteen years of R&D career, he worked as tester, R&D engineer, project manager, product manager and CTO. He is looking forward to the birth of his baby.",
"type": "Community"
}
}
}

View File

@ -32,17 +32,5 @@
},
"presskit": {
"title": "宣传资料"
},
"books": {
"title": "书籍"
},
"training": {
"title": "培训"
},
"communities": {
"title": "社区"
},
"tooling": {
"title": "工具与库"
}
}

View File

@ -25,17 +25,17 @@
"author": "",
"license": "ISC",
"dependencies": {
"@angular/common": "2.0.0-rc.3",
"@angular/compiler": "2.0.0-rc.3",
"@angular/core": "2.0.0-rc.3",
"@angular/forms": "0.1.1",
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.8",
"@angular/common": "2.0.0-rc.4",
"@angular/compiler": "2.0.0-rc.4",
"@angular/core": "2.0.0-rc.4",
"@angular/forms": "0.2.0",
"@angular/http": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.1",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.3",
"angular2-in-memory-web-api": "0.0.12",
"@angular/upgrade": "2.0.0-rc.4",
"angular2-in-memory-web-api": "0.0.14",
"bootstrap": "^3.3.6",
"core-js": "^2.4.0",
"reflect-metadata": "^0.1.3",

View File

@ -7,23 +7,23 @@
},
"license": "ISC",
"dependencies": {
"@angular/common": "2.0.0-rc.3",
"@angular/compiler": "2.0.0-rc.3",
"@angular/core": "2.0.0-rc.3",
"@angular/forms": "0.1.1",
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.8",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.3",
"@angular/common": "2.0.0-rc.4",
"@angular/compiler": "2.0.0-rc.4",
"@angular/core": "2.0.0-rc.4",
"@angular/forms": "0.2.0",
"@angular/http": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.1",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.4",
"core-js": "^2.4.0",
"reflect-metadata": "0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "0.6.12",
"angular2-in-memory-web-api": "0.0.12",
"angular2-in-memory-web-api": "0.0.14",
"bootstrap": "^3.3.6"
},
"devDependencies": {

View File

@ -11,16 +11,16 @@
},
"license": "ISC",
"dependencies": {
"@angular/common": "2.0.0-rc.3",
"@angular/compiler": "2.0.0-rc.3",
"@angular/core": "2.0.0-rc.3",
"@angular/forms": "0.1.1",
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.8",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.3",
"@angular/common": "2.0.0-rc.4",
"@angular/compiler": "2.0.0-rc.4",
"@angular/core": "2.0.0-rc.4",
"@angular/forms": "0.2.0",
"@angular/http": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.1",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.4",
"systemjs": "0.19.27",
"core-js": "^2.4.0",
@ -28,7 +28,7 @@
"rxjs": "5.0.0-beta.6",
"zone.js": "^0.6.12",
"angular2-in-memory-web-api": "0.0.12",
"angular2-in-memory-web-api": "0.0.14",
"bootstrap": "^3.3.6"
},
"devDependencies": {

View File

@ -1,7 +1,8 @@
/// <reference path="../_protractor/e2e.d.ts" />
'use strict';
describe('Security E2E Tests', () => {
beforeAll(function() { browser.get(''); });
beforeAll(() => browser.get(''));
it('sanitizes innerHTML', () => {
let interpolated = element(By.className('e2e-inner-html-interpolated'));
@ -13,13 +14,23 @@ describe('Security E2E Tests', () => {
expect(bold.getText()).toContain('Syntax');
});
it('escapes untrusted URLs', () => {
let untrustedUrl = element(By.className('e2e-dangerous-url'));
expect(untrustedUrl.getAttribute('href')).toMatch(/^unsafe:javascript/);
});
it('binds trusted URLs', () => {
let dangerousUrl = element(By.className('e2e-dangerous-url'));
expect(dangerousUrl.getAttribute('href')).toMatch(/^javascript:alert/);
let trustedUrl = element(By.className('e2e-trusted-url'));
expect(trustedUrl.getAttribute('href')).toMatch(/^javascript:alert/);
});
it('escapes untrusted resource URLs', () => {
let iframe = element(By.className('e2e-iframe-untrusted-src'));
expect(iframe.getAttribute('src')).toBe('');
});
it('binds trusted resource URLs', () => {
let iframe = element(By.className('e2e-iframe'));
let iframe = element(By.className('e2e-iframe-trusted-src'));
expect(iframe.getAttribute('src')).toMatch(/^https:\/\/www.youtube.com\//);
});
});

View File

@ -5,7 +5,7 @@ import { BypassSecurityComponent } from './bypass-security.component';
import { InnerHtmlBindingComponent } from './inner-html-binding.component';
@Component({
selector: 'app-root',
selector: 'my-app',
template: `
<h1>Security</h1>
<inner-html-binding></inner-html-binding>
@ -14,7 +14,7 @@ import { InnerHtmlBindingComponent } from './inner-html-binding.component';
directives: [
BypassSecurityComponent,
InnerHtmlBindingComponent,
],
]
})
export class AppComponent {
}

View File

@ -2,14 +2,19 @@
<h3>Bypass Security Component</h3>
<!--#docregion dangerous-url -->
<h4>A dangerous URL:</h4>
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me.</a></p>
<h4>A untrusted URL:</h4>
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
<h4>A trusted URL:</h4>
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
<!--#enddocregion dangerous-url -->
<!--#docregion iframe-videoid -->
<h4>Resource URL:</h4>
<p><label>Showing: <input (input)="updateVideoUrl($event.target.value)"></label></p>
<iframe class="e2e-iframe" width="640" height="390" [src]="videoUrl"></iframe>
<p>Trusted:</p>
<iframe class="e2e-iframe-trusted-src" width="640" height="390" [src]="videoUrl"></iframe>
<p>Untrusted:</p>
<iframe class="e2e-iframe-untrusted-src" width="640" height="390" [src]="dangerousVideoUrl"></iframe>
<!--#enddocregion iframe-videoid -->
<!--#enddocregion -->

View File

@ -8,14 +8,18 @@ import { DomSanitizationService, SafeResourceUrl, SafeUrl } from '@angular/platf
templateUrl: 'app/bypass-security.component.html',
})
export class BypassSecurityComponent {
dangerousUrl: SafeUrl;
dangerousUrl: string;
trustedUrl: SafeUrl;
dangerousVideoUrl: string;
videoUrl: SafeResourceUrl;
// #docregion trust-url
constructor(private sanitizer: DomSanitizationService) {
// javascript: URLs are dangerous if attacker controlled. Angular sanitizes them in data
// binding, but we can explicitly tell Angular to trust this value:
this.dangerousUrl = sanitizer.bypassSecurityTrustUrl('javascript:alert("Hi there")');
// javascript: URLs are dangerous if attacker controlled.
// Angular sanitizes them in data binding, but we can
// explicitly tell Angular to trust this value:
this.dangerousUrl = 'javascript:alert("Hi there")';
this.trustedUrl = sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
// #enddocregion trust-url
this.updateVideoUrl('PUBnlbjZFAI');
}
@ -23,11 +27,12 @@ export class BypassSecurityComponent {
// #docregion trust-video-url
updateVideoUrl(id: string) {
// Appending an ID to a YouTube URL is safe.
// Always make sure to construct SafeValue objects as close as possible to the input data, so
// Always make sure to construct SafeValue objects as
// close as possible to the input data, so
// that it's easier to check if the value is safe.
this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
this.videoUrl =
this.sanitizer.bypassSecurityTrustResourceUrl('https://www.youtube.com/embed/' + id);
this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}
// #enddocregion trust-video-url
}
// #enddocregion

View File

@ -11,4 +11,3 @@ export class InnerHtmlBindingComponent {
// E.g. a user/attacker controlled value from a URL.
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}
// #enddocregion inner-html-controller

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<title>Angular Content Security</title>
@ -21,6 +21,6 @@
</head>
<body>
<app-root>Loading...</app-root>
<my-app>Loading...</my-app>
</body>
</html>

View File

@ -5,9 +5,9 @@
*/
(function(global) {
var ngVer = '@2.0.0-rc.3'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.0.0-alpha.7'; // lock router version
var formsVer = '@0.1.1'; // lock forms version
var ngVer = '@2.0.0-rc.4'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.0.0-beta.1'; // lock router version
var formsVer = '@0.2.0'; // lock forms version
var routerDeprecatedVer = '@2.0.0-rc.2'; // temporarily until we update all the guides
//map tells the System loader where to look for things

View File

@ -589,18 +589,9 @@ bindon-ngModel
<div *ngFor="let hero of heroes trackBy:trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
</div>
<p>with <i>*ngForTrackBy</i></p>
<div class="box">
<!-- #docregion NgForTrackBy-2 -->
<div *ngFor="let hero of heroes" *ngForTrackBy="trackByHeroes">({{hero.id}}) {{hero.fullName}}</div>
<!-- #enddocregion NgForTrackBy-2 -->
</div>
<p>with <i>generic</i> trackById function</p>
<div class="box">
<!-- #docregion NgForTrackBy-3 -->
<div *ngFor="let hero of heroes" *ngForTrackBy="trackById">({{hero.id}}) {{hero.fullName}}</div>
<!-- #enddocregion NgForTrackBy-3 -->
<div *ngFor="let hero of heroes, trackBy:trackById">({{hero.id}}) {{hero.fullName}}</div>
</div>
<a class="to-toc" href="#toc">top</a>

View File

@ -4,7 +4,7 @@ import { HeroesComponent } from './heroes.component';
const routes: RouterConfig = [
{
path: '/heroes',
path: 'heroes',
component: HeroesComponent
}
];

View File

@ -1,25 +1,28 @@
/* tslint:disable */
// #docregion routestuff
import { ApplicationRef } from '@angular/core';
import { LocationStrategy } from '@angular/common';
import { Directive } from '@angular/core';
import { HTTP_PROVIDERS } from '@angular/http';
import {
ROUTER_PROVIDERS,
Router,
RouterLink,
RootRouter,
RouteRegistry,
ROUTER_PRIMARY_COMPONENT
} from '@angular/router-deprecated';
import { Observable } from 'rxjs/Rx';
import {
describe,
beforeEachProviders,
addProviders,
inject,
it,
expect,
MockApplicationRef
// MockApplicationRef
} from '@angular/core/testing';
import { MockLocationStrategy } from '@angular/common/testing';
import { SpyLocation } from '@angular/common/testing';
import {
TestComponentBuilder,
ComponentFixture
} from '@angular/compiler/testing';
} from '@angular/core/testing';
import { AppComponent } from '../app.component';
import { PhoneListComponent } from './phone-list.component';
@ -27,6 +30,11 @@ import { Phone, PhoneData } from '../core/phone/phone.service';
// #enddocregion routestuff
@Directive({
selector: '[routerLink]',
inputs: ['routeParams: routerLink', 'target: target']
})
class RouterLinkMock {}
class MockPhone extends Phone {
query(): Observable<PhoneData[]> {
@ -41,19 +49,22 @@ describe('PhoneList', () => {
// #docregion routestuff
beforeEachProviders(() => [
{ provide: Phone, useClass: MockPhone},
HTTP_PROVIDERS,
ROUTER_PROVIDERS,
{ provide: ApplicationRef, useClass: MockApplicationRef },
addProviders([
RouteRegistry,
{ provide: Router, useClass: RootRouter },
{ provide: ROUTER_PRIMARY_COMPONENT, useValue: AppComponent },
{ provide: LocationStrategy, useClass: MockLocationStrategy},
{ provide: Location, useClass: SpyLocation},
{ provide: Phone, useClass: MockPhone},
HTTP_PROVIDERS
]);
// #enddocregion routestuff
it('should create "phones" model with 2 phones fetched from xhr',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(PhoneListComponent)
return tcb
.overrideDirective(AppComponent, RouterLink, RouterLinkMock)
.overrideDirective(PhoneListComponent, RouterLink, RouterLinkMock)
.createAsync(PhoneListComponent)
.then((fixture: ComponentFixture<PhoneListComponent>) => {
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
@ -69,7 +80,10 @@ describe('PhoneList', () => {
it('should set the default value of orderProp model',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(PhoneListComponent)
return tcb
.overrideDirective(AppComponent, RouterLink, RouterLinkMock)
.overrideDirective(PhoneListComponent, RouterLink, RouterLinkMock)
.createAsync(PhoneListComponent)
.then((fixture: ComponentFixture<PhoneListComponent>) => {
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;

View File

@ -10,14 +10,14 @@
},
"license": "MIT",
"dependencies": {
"@angular/common": "2.0.0-rc.3",
"@angular/compiler": "2.0.0-rc.3",
"@angular/core": "2.0.0-rc.3",
"@angular/forms": "0.1.1",
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"@angular/router": "3.0.0-alpha.8",
"@angular/common": "2.0.0-rc.4",
"@angular/compiler": "2.0.0-rc.4",
"@angular/core": "2.0.0-rc.4",
"@angular/forms": "0.2.0",
"@angular/http": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.1",
"core-js": "^2.4.0",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.6",

View File

@ -3,7 +3,7 @@
"icon": "home",
"title": "Angular Docs",
"menuTitle": "Docs Home",
"banner": "Welcome to <b>Angular in JavaScript</b>! The current Angular 2 release is <b>rc.3</b>. Please consult the <a href='https://github.com/angular/angular/blob/master/CHANGELOG.md' target='_blank'> Change Log</a> about recent enhancements, fixes, and breaking changes."
"banner": "Welcome to <b>Angular in JavaScript</b>! The current Angular 2 release is <b>rc.4</b>. Please consult the <a href='https://github.com/angular/angular/blob/master/CHANGELOG.md' target='_blank'> Change Log</a> about recent enhancements, fixes, and breaking changes."
},
"quickstart": {

View File

@ -3,7 +3,7 @@
"icon": "home",
"title": "Angular文档",
"menuTitle": "文档首页",
"banner": "欢迎来到 <b>Angular in TypeScript</b>! 当前的Angular版本是 <b>rc.3</b>。请参考<a href='https://github.com/angular/angular/blob/master/CHANGELOG.md' target='_blank'>变更记录</a>、最新功能、BUG修复和重大的破坏性更改。"
"banner": "欢迎来到 <b>Angular in TypeScript</b>! 当前的Angular版本是 <b>rc.4</b>。请参考<a href='https://github.com/angular/angular/blob/master/CHANGELOG.md' target='_blank'>变更记录</a>、最新功能、BUG修复和重大的破坏性更改。"
},
"cli-quickstart": {

View File

@ -3,7 +3,7 @@ include ../_util-fns
.alert.is-important
:marked
The Component Router is in alpha release. This is the recommended Angular 2 router and supersedes
The Component Router is in beta release. This is the recommended Angular 2 router and supersedes
the earlier *deprecated beta* and *v2* routers.
组件路由器已经进入了Alpha阶段推荐在Angular 2中使用此路由器以取代早前*废弃的beta版*及*第二版*路由器。
@ -1612,7 +1612,7 @@ h3#nav-to-list 导航回列表组件
除非我们能学到点新东西,否则这种练习就没啥亮点。
不过,我们已经有了一些新主意和新技巧:
* We'd like our route URLs to branch in to child route trees that reflect the component treese in our feature areas.
* We'd like our route URLs to branch in to child route trees that reflect the component trees in our feature areas.
* 我们希望把这些路由地址组织成一棵子路由树,它应该能反映本特性区中组件树的结构。
@ -1909,8 +1909,8 @@ code-example(format="").
:marked
Since we only want to redirect when our path specifically matches `''`, we've added an extra configuration
to our route using `terminal: true`. Mainly for redirects, the `terminal` property gives us more control over
when the router should continue matching our URL against our defined routes.
to our route using `terminal: true`. Mainly for redirects, the `terminal` property tells the router
whether or not it should continue matching our URL against the rest of our defined routes.
由于我们希望只有在路径明确的匹配到`''`时才重定向,所以我们往路由中添加了一个额外的配置项:`terminal: true`。
主要是为了重定向,`terminal`属性是用来控制路由器是否应该继续匹配URL和我们定义的路由。译者注`terminal`设置为`true`时,该路由的优先级别就低于其他路由,只有在所有其他路由都不匹配的时候才最后匹配这个路由。主要是为了标示专用于重定向的路由而设计的。)

View File

@ -1,7 +1,7 @@
block includes
include ../_util-fns
:marked
Web application security has many aspects. This documentation describes Angular's built in
Web application security has many aspects. This chapter describes Angular's built in
protections against common web application vulnerabilities and attacks, such as Cross Site
Scripting Attacks. It does not cover application level security, such as authentication (_Who is
this user?_) or authorization (_What can this user do?_).
@ -97,7 +97,7 @@ h2#xss 防范跨站脚本(XSS)攻击
:marked
[Cross-Site Scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) enables attackers
to inject malicious code into web pages. Such code can then for example steal user's data (in
to inject malicious code into web pages. Such code can then, for example, steal user's data (in
particular their login data), or perform actions impersonating the user. This is one of the most
common attacks on the web.
@ -151,7 +151,7 @@ h2#xss 防范跨站脚本(XSS)攻击
Angular定义了四个安全环境HTML样式URL和资源URL。
* HTML is used when interpreting a value as HTML, e.g. when binding to `innerHtml`
* HTML is used when interpreting a value as HTML, e.g., when binding to `innerHtml`
* HTML值需要被解释为HTML时使用比如当绑定到`innerHTML`时。
@ -163,7 +163,7 @@ h2#xss 防范跨站脚本(XSS)攻击
* URL值需要被用作URL属性时使用比如`<a href>`。
* Resource URLs are URLs that will be loaded and executed as code, e.g. in `<script src>`
* Resource URLs are URLs that will be loaded and executed as code, e.g., in `<script src>`
* 资源URL值需要被当做代码而加载并执行时使用比如`<script src>`中的URL。
@ -183,7 +183,7 @@ h2#xss 防范跨站脚本(XSS)攻击
下面的例子绑定了`htmlSnippet`的值,一次把它放进插值表达式里,另一次把它绑定到元素的`innerHTML`属性上。
+makeExample('security/ts/app/inner-html-binding.component.html')(format=".")
+makeExample('app/inner-html-binding.component.html')
:marked
Interpolated content is always escaped - the HTML is not interpreted, and the browser displays
@ -198,7 +198,7 @@ h2#xss 防范跨站脚本(XSS)攻击
如果希望这段HTML被正常解释就必须绑定到一个HTML属性上比如`innerHTML`。但是如果把一个可能被攻击者控制的值绑定到`innerHTML`就会导致XSS漏洞。
比如,包含在`<script>`标签的代码就会被执行。
+makeExample('security/ts/app/inner-html-binding.component.ts', 'inner-html-controller')(format=".")
+makeExcerpt('app/inner-html-binding.component.ts ()', 'inner-html-controller')
:marked
Angular recognizes the value as unsafe, and automatically sanitizes it. It removes the `<script>`
@ -227,8 +227,7 @@ figure.image-display
### 内容安全策略
A [Content Security Policy (CSP)]
(http://www.html5rocks.com/en/tutorials/security/content-security-policy/) is a defense-in-depth
A [Content Security Policy (CSP)](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) is a defense-in-depth
technique to prevent XSS. To enable CSP, configure your web server to return an appropriate
`Content-Security-Policy` HTTP header.
@ -257,7 +256,7 @@ figure.image-display
### 服务器端XSS保护
HTML constructed on the server is vulnerable to injection attacks. Injecting template code into an
Angular application is the same as injecting executable code (e.g. JavaScript) into the
Angular application is the same as injecting executable code into the
application; it gives the attacker full control over the application. To prevent this, make sure
to use a templating language that automatically escapes values to prevent XSS vulnerabilities on
the server. Do not generate Angular templates on the server side using a templating language, this
@ -301,15 +300,16 @@ h2#bypass-security-apis 信任安全的值
记住,一个值是否安全取决于它所在的环境,所以你要为这个值按预定的用法选择正确的环境。假设下面的模板需要把`javascript.alert(...)`方法绑定到URL。
+makeExample('security/ts/app/bypass-security.component.html', 'dangerous-url')(format=".")
+makeExcerpt('app/bypass-security.component.html ()', 'dangerous-url')
:marked
Normally, Angular would automatically sanitize the URL and disable the dangerous code. To prevent
Normally, Angular automatically sanitizes the URL, disables the dangerous code and,
in development mode, logs this action to the console. To prevent
this, we can mark the URL value as a trusted URL using the `bypassSecurityTrustUrl` call:
通常Angular会自动无害化这个URL并禁止危险的代码。为了防止这种行为我们可以调用`bypassSecurityTrustUrl`把这个URL值标记为一个可信任的URL
+makeExample('security/ts/app/bypass-security.component.ts', 'trust-url')(format=".")
+makeExcerpt('app/bypass-security.component.ts ()', 'trust-url')
figure.image-display
img(src='/resources/images/devguide/security/bypass-security-component.png'
@ -319,7 +319,7 @@ figure.image-display
If we need to convert user input into a trusted value, it can be convenient to do so in a
controller method. The template below allows users to enter a YouTube video ID, and load the
corresponding video in an `<iframe>`. The `<iframe src>` attribute is a resource URL security
context, because an untrusted source can e.g. smuggle in file downloads that unsuspecting users
context, because an untrusted source can, e.g., smuggle in file downloads that unsuspecting users
would execute. So we call a method on the controller to construct a trusted video URL, which
Angular then allows binding into `<iframe src>`.
@ -327,9 +327,9 @@ figure.image-display
然后把相应的视频加载到`<iframe>`中。`<iframe src>`是一个“资源URL”的安全环境因为不可信的源码可能作为文件下载到本地被毫无防备的用户执行。
所以我们要调用一个控制器方法来构造一个新的、可信任的视频URL然后把它绑定到`<iframe src>`。
+makeExample('security/ts/app/bypass-security.component.html', 'iframe-videoid')(format=".")
+makeExcerpt('app/bypass-security.component.html ()', 'iframe-videoid')
+makeExample('security/ts/app/bypass-security.component.ts', 'trust-video-url')(format=".")
+makeExcerpt('app/bypass-security.component.ts ()', 'trust-video-url')
.l-main-section
h2#http HTTP-level Vulnerabilities
@ -350,16 +350,16 @@ h3#xsrf 跨站请求伪造XSRF
:marked
In a Cross-site Request Forgery (XSRF or CSRF), an attacker tricks the user into visiting a
_different_ page, and has them e.g. submit a form that sends a request to your application's
_different_ page, and has them, e.g., submit a form that sends a request to your application's
web server. If the user is logged into your application, the browser will send authentication
cookies, and the attacker could - for example - cause a bank transfer in the user's name with
cookies, and the attacker could &mdash; for example &mdash; cause a bank transfer in the user's name with
the right request.
在跨站请求伪造XSRF或CSFR一个攻击者会欺骗用户让他们访问_另一个_页面并提交一个表单
向你应用程序的Web服务器发送一个请求。如果用户已经登录到你的应用程序浏览器就会发送该用户的认证Cookie
这样攻击者就可以发送一个正确的请求,以该用户的名义发起一次银行转账。
To prevent this, your application must make sure that user requests originate in your own
To prevent this, your application must ensure that user requests originate in your own
application, not on a different site. A common technique is that the server sends a randomly
generated authentication token in a cookie, often with the name `XSRF-TOKEN`. Cookies can only
be read by the website on which they are set, so only your own application can read this token. On
@ -387,17 +387,21 @@ h3#xsrf 跨站请求伪造XSRF
Angular applications can customize cookie and header names by binding their own
`CookieXSRFStrategy` value, or implement an entirely custom `XSRFStrategy` by providing a custom
binding for that type, by adding
`provide(XSRFStrategy, {useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name')})` or
`provide(XSRFStrategy, {useClass: MyXSRFStrategy})` to your providers list.
binding for that type, by adding either of the following to your providers list:
Angular应用程序可以通过绑定它们自己的`CookieXSRFStrategy`值来自定义cookie和HTTP头的名字
也可以通过提供一个自定义类型绑定来完全制定`XSRFStrategy`,只要把`provide(XSRFStrategy, {useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name')})`或`provide(XSRFStrategy, {useClass: MyXSRFStrategy})`加到你的供应商列表里就可以了。
也可以通过提供一个自定义类型绑定来完全制定`XSRFStrategy`
只要把下列代码之一加到你的供应商列表里就可以了:
code-example(language="typescript").
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name')}
{ provide: XSRFStrategy, useClass: MyXSRFStrategy}
:marked
Learn about Cross Site Request Forgery (XSRF) at the Open Web Application Security Project (OWASP)
[here](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29) and
[here](https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet). This [Stanford University
paper](https://seclab.stanford.edu/websec/csrf/csrf.pdf) is a rich source of detail.
paper](https://seclab.stanford.edu/websec/csrf/csrf.pdf) is also a rich source of detail.
到开放式Web应用程序安全项目(OWASP)的[这里](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29)
和[这里](https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet)学习更多关于跨站请求伪造XSRF的知识。

View File

@ -1886,11 +1886,11 @@ block dart-no-truthy-falsey
+makeExample('template-syntax/ts/app/app.component.ts', 'trackByHeroes')(format=".")
:marked
Now set the `NgForTrackBy` directive to that *tracking* function.
Angular offers a variety of equivalent syntax choices including these two:
现在,把`NgForTrackBy`指令设置为那个*追踪*函数。
Angular从语法上提供了等价的可选变体比如这两个
+makeExample('template-syntax/ts/app/app.component.html', 'NgForTrackBy-2')(format=".")
:marked
The *tracking* function doesn't eliminate all DOM changes.
Angular may have to update the DOM element if the same-hero *properties* have changed.

View File

@ -1,11 +1,22 @@
.grid-fluid.l-space-bottom-2
.c12.text-center
h3.text-headline.text-uppercase Core Team
h3.text-headline.text-uppercase 核心团队
.clear
.grid-fluid
.c6
.article-card
.date June 30, 2016
.title
a(
target="_blank"
href="http://angularjs.blogspot.com/2016/06/rc4-now-available.html"
) RC2 Now Available
p Today were happy to announce that we are shipping Angular 2.0.0-rc4. This release begins to lay the foundation for improved Angular Compilation, and makes improvements to testing....
.author
img(src="/resources/images/bios/stephenfluin.jpg")
.posted Posted by <b>Stephen Fluin</b>
.c6
.article-card
.date June 21, 2016
@ -14,116 +25,70 @@
target="_blank"
href="http://angularjs.blogspot.com/2016/06/rc3-now-available.html"
) RC3 Now Available
p oday were happy to announce that we are shipping Angular 2.0.0-rc3. This release includes a fix for a major performance regression in RC2...
p Today were happy to announce that we are shipping Angular 2.0.0-rc3. This release includes a fix for a major performance regression in RC2...
.author
img(src="/resources/images/bios/stephenfluin.jpg")
.posted 发稿人:<b>Stephen Fluin</b>
.c6
.article-card
.date June 15, 2016
.title
a(
target="_blank"
href="http://angularjs.blogspot.com/2016/06/rc2-now-available.html"
) RC2 Now Available
p Today were happy to announce that we are shipping Angular 2.0.0-rc2. This release includes 1. Animation Framework 2. Improvements to Forms 3. More than 100 community contributions...
.author
img(src="/resources/images/bios/stephenfluin.jpg")
.posted 发稿人: <b>Stephen Fluin</b>
.posted Posted by <b>Stephen Fluin</b>
.grid-fluid.l-space-bottom-2.l-space-top-4
.c12.text-center
h3.text-headline.text-uppercase Developer Community
h3.text-headline.text-uppercase 开发者社区
.clear
.grid-fluid
.c6
.article-card
.date 2016年6月14日
.date June 30, 2016
.title
a(
target="_blank"
href="http://www.bennadel.com/blog/3116-using-an-item-template-with-an-html-dropdown-menu-component-in-angular-2-rc-3.htm"
) Using An Item Template With An HTML Dropdown Menu Component
p A while ago, I played around with trying to create an HTML Dropdown menu component in Angular 2. I discovered that you could pass Template references into components for dynamic rendering....
.author
img(src="/resources/images/bios/shield-bio-placeholder.png")
.posted Posted by <b>Ben Nadel</b>
.c6
.article-card
.date June 29, 2016
.title
a(
target="_blank"
href="https://channel9.msdn.com/Shows/Office-Dev-Show/Office-Dev-Show-Episode-35-Getting-Started-with-Angular-2-and-the-Microsoft-Graph"
) Getting Started with Angular 2 and the Microsoft Graph (Video)
p Richard diZerega explores how to connect to the Microsoft Graph from Angular 2 and TypeScript. Richard starts with the Angular 2 quickstart template and gets it connecting to the the Microsoft Graph...
.author
img(src="/resources/images/bios/shield-bio-placeholder.png")
.posted Posted by <b>Richard diZerega</b>
.grid-fluid
.c6
.article-card
.date June 26, 2016
.title
a(
target="_blank"
href="http://blog.mgechev.com/2016/06/26/tree-shaking-angular2-production-build-rollup-javascript/"
) Building an Angular 2 Application for Production
p During the keynote of ng-conf, the core team managed to drop the size of the “Hello world!” app to less than 50K! In this blog post well explain all the steps we need to go through in order to achieve such results!.
.author
img(src="/resources/images/bios/shield-bio-placeholder.png")
.posted Posted by <b>Minko Gechev</b>
.c6
.article-card
.date June 14, 2016
.title
a(
target="_blank"
href="http://blog.thoughtram.io/angular/2016/06/14/routing-in-angular-2-revisited.html"
) Routing in Angular 2 Revisited
a(
target="_blank"
href="http://blog.thoughtram.io/angular/2016/06/14/routing-in-angular-2-revisited.html"
) 重新考虑Angular 2的路由
p Just recently, the Angular team announced yet another version of the new router. Take a first look at the new and better APIs, touching on the most common scenarios...
p 最近Angular团队宣布了又一个新路由器版本。抢先看看这些崭新、更好的API涵盖最常用的场景...
.author
img(src="/resources/images/bios/pascalprecht.jpg")
.posted 发稿人: <b>Pascal Precht</b>
.posted Posted by <b>Pascal Precht</b>
.c6
.article-card
.date 2016年6月13日
.title
a(
target="_blank"
href="https://toddmotto.com/rewriting-angular-styleguide-angular-2"
) A new Angular 1.x ES2015 styleguide, the path to Angular 2
a(
target="_blank"
href="https://toddmotto.com/rewriting-angular-styleguide-angular-2"
) 全新Angular 1.x ES2015风格指南走向Angular 2
p Angular 1.x has changed vastly since the original styleguide, and ES6/ES2015 has now become a defacto standard. The new styleguide focuses on using ES2015, offering recommendations on tooling to use it today...
p 从原始的风格指南到现在Angular 1.x发生了很大的变化而且ES6/ES2015也变成了事实上的新标准. 这个新的风格指南的重点是使用了ES2015提供了环境和工具推荐让我们可以现在就使用ES20155标准...
.author
img(src="/resources/images/bios/shield-bio-placeholder.png")
.posted 发稿人:<b>Todd Motto</b>
.grid-fluid
.c6
.article-card
.date 2016年6月9日
.title
a(
target="_blank"
href="https://medium.com/@urish/building-simon-with-angular2-iot-fceb78bb18e5"
) Building Simon with Angular2-IoT
a(
target="_blank"
href="https://medium.com/@urish/building-simon-with-angular2-iot-fceb78bb18e5"
) 使用Angular2-IoT建造西蒙游戏
p I thought it would be fun to see if I could make the same [Angular 2] control/logic code for both a web application and a physical, “Internet of Things” device....
p 把同样的一套Angular 2的控制器和逻辑代码应用到一个网络应用程序和一个物理的“物联网”设备....
.author
img(src="/resources/images/bios/angular-gde-bio-placeholder.png")
.posted 发稿人:<b>Uri Shaked</b>
.c6
.article-card
.date 2016年6月8日
.title
a(
target="_blank"
href="http://blog.thoughtram.io/angular/2016/06/08/component-relative-paths-in-angular-2.html"
) Component-Relative Paths in Angular 2
a(
target="_blank"
href="http://blog.thoughtram.io/angular/2016/06/08/component-relative-paths-in-angular-2.html"
) Angular 2组件的相对路径
p Component-based development is Angular 2s most-loved feature. By now you should be familiar with using the @Component decorators to create components.\...
p Angular 2最受欢迎的特征就是基于组件的开发。到现在你应该对使用@Component装饰器来创建组件很熟悉\...
.author
img(src="/resources/images/bios/thomas.jpg")
.posted 发稿人:<b>Thomas Burleson</b>
.grid-fluid.l-space-bottom-2.l-space-top-4
.c12.text-center
h3.text-headline.text-uppercase Twitter
@ -131,7 +96,9 @@
.grid-fluid
.c3
p
.c6
.article-card
.title
a(
@ -139,11 +106,6 @@
class="twitter-follow-button"
data-show-count="false"
) Follow @angularjs
a(
href="http://twitter.com/angularjs"
class="twitter-follow-button"
data-show-count="false"
) 关注 @angularjs
p.
<a class="twitter-timeline" data-chrome="nofooter noborders noheader"
href="http://twitter.com/angularjs" data-widget-id="700150278465523713"></a>

View File

@ -1,6 +1,5 @@
{
"index": {
"title": "资源库",
"subtitle": "Angular 2的资源库"
"title": "浏览Angular的资源库"
}
}

View File

@ -1,18 +1,126 @@
.resources {
display: flex;
justify-content: space-between;
flex-direction: row-reverse;
@media(max-width: 768px) {
justify-content: center;
flex-direction: column-reverse;
.h-affix {
position: fixed;
}
a {
font-size: 16px;
.affix-top {
top: 50px;
}
.c-resource {
h4 {
margin: 0;
line-height: 24px;
}
p {
margin: 0;
}
}
.c-resource-nav {
margin-top: 48px;
width: $unit * 20;
z-index: $layer-1;
background-color: #fff;
border-radius: 2px;
a {
color: #373E41;
text-decoration: none;
}
.category {
padding: 10px 0;
.category-link {
display: block;
margin: 2px 0;
padding: 3px 14px;
font-size: 18px !important;
&:hover {
background: #edf0f2;
color: #2B85E7;
}
}
}
.subcategory {
.subcategory-link {
display: block;
margin: 2px 0;
padding: 4px 14px;
&:hover {
background: #edf0f2;
color: #2B85E7;
}
}
}
}
.h-anchor-offset {
display: block;
position: relative;
top: -20px;
visibility: hidden;
}
.l-flex--column {
display: flex;
flex-direction: column;
}
.c-resource-header {
margin-bottom: 16px;
}
.c-contribute {
margin-bottom: 24px;
}
.c-resource-header h2 {
margin: 0;
}
.subcategory-title {
padding: 16px 23px;
margin: 0;
background-color: $mist;
color: #373E41;
}
.h-capitalize {
text-transform: capitalize;
}
.h-hide {
display: none;
}
.resource-row-link {
color: #1a2326;
border: transparent solid 1px;
margin: 0;
padding: 16px 23px 16px 23px;
position: relative;
text-decoration: none;
transition: all .3s;
}
.resource-row-link:hover {
text-decoration: none;
border-color: #2B85E7;
border-radius: 4px;
box-shadow: 0 8px 8px rgba(1, 67, 163, .24), 0 0 8px rgba(1, 67, 163, .12), 0 6px 18px rgba(43, 133, 231, .12);
transform: translate3d(0, -2px, 0);
}
@media(max-width: 900px) {
.c-resource-nav {
display: none;
}
}
}
.capitalize {
text-transform: capitalize;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,44 @@
<div class="resources js-resources-ctrl grid-fixed" ng-controller="ResourcesCtrl as ctrl">
<div class="c8">
<div class="l-flex--column">
<div class="showcase" ng-repeat="(category, categoryObj) in ctrl.fbObject">
<header class="c-resource-header">
<a class="h-anchor-offset" name="{{category}}"></a>
<h2 class="text-headline text-uppercase">{{ category }}</h2>
</header>
<div class="shadow-1">
<div ng-repeat="(subCategory, subcategoryObj) in categoryObj">
<a class="h-anchor-offset" name="{{subCategory}}"></a>
<h3 class="text-uppercase subcategory-title">{{subCategory}}</h3>
<div ng-repeat="(section, sectionObj) in subcategoryObj">
<div ng-repeat="resource in sectionObj">
<div class="c-resource" ng-if="resource.rev">
<a class="l-flex--column resource-row-link" target="_blank" href="{{resource.url}}">
<div>
<h4>{{ resource.title }}</h4>
<p class="resource-description" ng-if="resource.desc">{{ resource.desc }}</p>
<p class="resource-description" ng-if="!resource.desc">No Description</p>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="c3">
<div class="c-resource-nav shadow-1 l-flex--column h-affix" ng-class="{ 'affix-top': ctrl.scrollPos > 200 }">
<div class="category" ng-repeat="(category, categoryObj) in ctrl.fbObject">
<a class="category-link h-capitalize" href="#{{ category }}">{{ category }}</a>
<div class="subcategory" ng-repeat="(subCategory, subcategoryObj) in categoryObj">
<a class="subcategory-link" href="#{{subCategory}}">{{subCategory}}</a>
</div>
</div>
</div>
</div>
</div>