1. Vue d’ensemble
Dans ce didacticiel rapide, nous allons mettre à niveau notre lien d’application angulaire existant:/rest-api-spring-oauth2-angularjs[décrit]ici, pour utiliser Angular 4 au lieu d’AngularJS.
2. Configuration angulaire4
Tout d’abord, nous utiliserons Angular CLI pour générer et gérer nos modules front-end.
-
Nous allons d’abord installer node and npm ** - Angular CLI étant un outil npm.
Ensuite, Inclure les dépendances Maven , nous devons utiliser frontend-maven-plugin pour construire notre projet Angular en utilisant maven:
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<nodeVersion>v6.10.2</nodeVersion>
<npmVersion>3.10.10</npmVersion>
<workingDirectory>src/main/resources</workingDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Et enfin, générer un nouveau module en utilisant un CLI angulaire:
ng new oauthApp
Notez que nous aurons deux modules frontaux - un pour le flux de mots de passe et l’autre pour le flux implicite.
Dans les sections suivantes, nous aborderons la logique d’application angulaire pour chaque module.
3. Mot de passe utilisant Angular4
Ensuite, abordons la logique de notre module frontal Password Flow.
3.1. Service App
Commençons par notre AppService - situé à app.service.ts - qui contient la logique pour les interactions de serveur:
-
obtainAccessToken () : pour obtenir le jeton d’accès en fonction des informations d’identification de l’utilisateur
-
saveToken () : enregistrer notre jeton d’accès dans un cookie en utilisant ng2-cookies
bibliothèque ** getResource () : pour obtenir un objet Foo du serveur à l’aide de son ID
-
checkCredentials () : pour vérifier si l’utilisateur est connecté ou non
-
logout () : pour supprimer le cookie de jeton d’accès et déconnecter l’utilisateur
export class Foo {
constructor(
public id: number,
public name: string) { }
}
@Injectable()
export class AppService {
constructor(
private __router: Router, private __http: Http){}
obtainAccessToken(loginData){
let params = new URLSearchParams();
params.append('username',loginData.username);
params.append('password',loginData.password);
params.append('grant__type','password');
params.append('client__id','fooClientIdPassword');
let headers = new Headers({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Basic '+btoa("fooClientIdPassword:secret")});
let options = new RequestOptions({ headers: headers });
this.__http.post('http://localhost:8081/spring-security-oauth-server/oauth/token', params.toString(), options)
.map(res => res.json())
.subscribe(
data => this.saveToken(data),
err => alert('Invalid Credentials'));
}
saveToken(token){
var expireDate = new Date().getTime() + (1000 ** token.expires__in);
Cookie.set("access__token", token.access__token, expireDate);
this.__router.navigate(['/']);
}
getResource(resourceUrl) : Observable<Foo>{
var headers = new Headers({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Bearer '+Cookie.get('access__token')});
var options = new RequestOptions({ headers: headers });
return this.__http.get(resourceUrl, options)
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
checkCredentials(){
if (!Cookie.check('access__token')){
this.__router.navigate(['/login']);
}
}
logout() {
Cookie.delete('access__token');
this.__router.navigate(['/login']);
}
}
3.2. Composant de connexion
Voyons maintenant notre LoginComponent qui est responsable du formulaire de login:
@Component({
selector: 'login-form',
providers:[AppService],
template: `<h1>Login</h1>
<input type="text"[(ngModel)]="loginData.username"/>
<input type="password" [(ngModel)]="loginData.password"/>
<button (click)="login()" type="submit">Login</button>`
})
export class LoginComponent {
public loginData = {username: "", password: ""};
constructor(private __service:AppService) {}
login() {
this.__service.obtainAccessToken(this.loginData);
}
}
3.3. Composant d’accueil
Ensuite, notre HomeComponent qui est responsable de l’affichage et de la manipulation de notre page d’accueil:
@Component({
selector: 'home-header',
providers:[AppService],
template: `<span>Welcome !!</span>
<a (click)="logout()" href="#">Logout</a>
<foo-details></foo-details>`
})
export class HomeComponent {
constructor(
private __service:AppService){}
ngOnInit(){
this.__service.checkCredentials();
}
logout() {
this.__service.logout();
}
}
3.4. Composant Foo
Enfin, notre FooComponent pour afficher nos détails Foo:
@Component({
selector: 'foo-details',
providers:[AppService],
template: `<h1>Foo Details</h1>
<label>ID</label> <span>{{foo.id}}</span>
<label>Name</label> <span>{{foo.name}}</span>
<button (click)="getFoo()" type="submit">New Foo</button>`
})
export class FooComponent {
public foo = new Foo(1,'sample foo');
private foosUrl = 'http://localhost:8082/spring-security-oauth-resource/foos/';
constructor(private __service:AppService) {}
getFoo(){
this.__service.getResource(this.foosUrl+this.foo.id)
.subscribe(
data => this.foo = data,
error => this.foo.name = 'Error');
}
}
3.5. Composant d’application
Notre simple AppComponent pour agir en tant que composant racine:
@Component({
selector: 'app-root',
template: `<router-outlet></router-outlet>`
})
export class AppComponent {}
Et le AppModule où nous enveloppons tous nos composants, services et itinéraires:
@NgModule({
declarations:[ AppComponent,
HomeComponent,
LoginComponent,
FooComponent
],
imports:[ BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot([ { path: '', component: HomeComponent },
{ path: 'login', component: LoginComponent }])
],
providers:[],
bootstrap:[AppComponent]})
export class AppModule { }
4. Flux implicite
Ensuite, nous nous concentrerons sur le module Flux implicite.
4.1. Service App
De même, nous commencerons par notre service, mais cette fois-ci, nous utiliserons la bibliothèque angular-oauth2-oidc au lieu d’obtenir nous-mêmes un jeton d’accès:
@Injectable()
export class AppService {
constructor(
private __router: Router, private __http: Http, private oauthService: OAuthService){
this.oauthService.loginUrl = 'http://localhost:8081/spring-security-oauth-server/oauth/authorize';
this.oauthService.redirectUri = 'http://localhost:8086/';
this.oauthService.clientId = "sampleClientId";
this.oauthService.scope = "read write foo bar";
this.oauthService.setStorage(sessionStorage);
this.oauthService.tryLogin({});
}
obtainAccessToken(){
this.oauthService.initImplicitFlow();
}
getResource(resourceUrl) : Observable<Foo>{
var headers = new Headers({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Bearer '+this.oauthService.getAccessToken()});
var options = new RequestOptions({ headers: headers });
return this.__http.get(resourceUrl, options)
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
isLoggedIn(){
if (this.oauthService.getAccessToken() === null){
return false;
}
return true;
}
logout() {
this.oauthService.logOut();
location.reload();
}
}
4.2. Composant d’accueil
Notre HomeComponent pour gérer notre page d’accueil simple:
@Component({
selector: 'home-header',
providers:[AppService],
template: `
<button ** ngIf="!isLoggedIn" (click)="login()" type="submit">Login</button>
<div ** ngIf="isLoggedIn">
<span>Welcome !!</span>
<a (click)="logout()" href="#">Logout</a>
<br/>
<foo-details></foo-details>
</div>`
})
export class HomeComponent {
public isLoggedIn = false;
constructor(
private __service:AppService){}
ngOnInit(){
this.isLoggedIn = this.__service.isLoggedIn();
}
login() {
this.__service.obtainAccessToken();
}
logout() {
this.__service.logout();
}
}
4.3. Composant Foo
Notre FooComponent est exactement le même que dans le module de flux de mots de passe.
4.4. Module d’application
Enfin, notre AppModule :
@NgModule({
declarations:[ AppComponent,
HomeComponent,
FooComponent
],
imports:[ BrowserModule,
FormsModule,
HttpModule,
OAuthModule.forRoot(),
RouterModule.forRoot([ { path: '', component: HomeComponent }])
],
providers:[],
bootstrap:[AppComponent]})
export class AppModule { }
5. Exécuter le front end
{vide} 1. Pour exécuter l’un de nos modules front-end, nous devons d’abord créer l’application:
mvn clean install
{vide} 2. Ensuite, nous devons accéder à notre répertoire d’applications angulaires:
cd src/main/resources
{vide} 3. Enfin, nous allons commencer notre application:
npm start
Le serveur démarrera par défaut sur le port 4200, pour changer de port de module, le
"start": "ng serve"
dans package.json pour le faire fonctionner sur le port 8086, par exemple:
"start": "ng serve --port 8086"
6. Conclusion
Dans ce rapide didacticiel, nous avons vu comment mettre à niveau une application AngularJS vers une application utilisant un frontal Angular4.
Comme toujours, le code source complet peut être trouvé à l’adresse over sur GitHub .