Front-End-App mit Spring Security OAuth - Autorisierungscode-Fluss

Front-End-App mit Spring Security OAuth - Berechtigungscode-Fluss

1. Überblick

In diesem Tutorial setzen wir unsereSpring Security OAuth series fort, indem wir ein einfaches Frontend für den Ablauf des Autorisierungscodes erstellen.

Denken Sie daran, dass der Fokus hier auf der Client-Seite liegt. Schauen Sie sich die Beschreibung vonSpring REST API + OAuth2 + AngularJSan, um die detaillierte Konfiguration für Autorisierungs- und Ressourcenserver zu überprüfen.

2. Autorisierungsserver

Bevor wir unser Front-End erreichen, müssen wir unsere Client-Details in unserer Authorization Server-Konfiguration hinzufügen:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
               .withClient("fooClientId")
               .secret(passwordEncoder().encode("secret"))
               .authorizedGrantTypes("authorization_code")
               .scopes("foo", "read", "write")
               .redirectUris("http://localhost:8089/")
...

Beachten Sie, wie wir jetzt den Berechtigungscode-Grant-Typ aktiviert haben, mit den folgenden einfachen Details:

  • Unsere Kunden-ID lautetfooClientId

  • Unsere Bereiche sindfoo,read andwrite

  • Der Umleitungs-URI isthttp://localhost:8089/ (wir werden Port 8089 für unsere Front-End-App verwenden).

3. Das Frontend

Beginnen wir jetzt mit der Erstellung unserer einfachen Front-End-Anwendung.

Da wir hier Angular 6 für unsere App verwenden werden, müssen wir dasfrontend-maven-plugin-Plugin in unserer Spring Boot-Anwendung verwenden:


    com.github.eirslett
    frontend-maven-plugin
    1.6

    
        v8.11.3
        6.1.0
        src/main/resources
    

    
        
            install node and npm
            
                install-node-and-npm
            
        

        
            npm install
            
                npm
            
        

        
            npm run build
            
                npm
            

            
                run build
            
        
    

Beachten Sie, dass wir natürlich zuerstNode.js auf unserer Box installieren müssen. Wir verwenden die Angular-CLI, um die Basis für unsere App zu generieren:

ng new authCode

4. Winkelmodul

Lassen Sie uns nun unser Winkelmodul im Detail diskutieren.

Hier sind unsere einfachenAppModule:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule }   from '@angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home.component';
import { FooComponent } from './foo.component';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    FooComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    RouterModule.forRoot([
     { path: '', component: HomeComponent, pathMatch: 'full' }], {onSameUrlNavigation: 'reload'})
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Unser Modul besteht aus drei Komponenten und einem Service. Wir werden sie in den folgenden Abschnitten behandeln

4.1. App-Komponente

Beginnen wir mit unserenAppComponent, der Stammkomponente:

import {Component} from '@angular/core';

@Component({
    selector: 'app-root',
    template: `
`
})

export class AppComponent {}

4.2. Hauptkomponente

Als nächstes kommt unsere HauptkomponenteHomeComponent:

import {Component} from '@angular/core';
import {AppService} from './app.service'

@Component({
    selector: 'home-header',
    providers: [AppService],
  template: `
Welcome !! Logout
` }) export class HomeComponent { public isLoggedIn = false; constructor( private _service:AppService){} ngOnInit(){ this.isLoggedIn = this._service.checkCredentials(); let i = window.location.href.indexOf('code'); if(!this.isLoggedIn && i != -1){ this._service.retrieveToken(window.location.href.substring(i + 5)); } } login() { window.location.href = 'http://localhost:8081/spring-security-oauth-server/oauth/authorize?response_type=code&client_id=' + this._service.clientId + '&redirect_uri='+ this._service.redirectUri; } logout() { this._service.logout(); } }

Beachten Sie, dass:

  • Wenn der Benutzer nicht angemeldet ist, wird nur die Anmeldeschaltfläche angezeigt

  • Die Anmeldeschaltfläche leitet den Benutzer zur Autorisierungs-URL weiter

  • Wenn der Benutzer mit dem Autorisierungscode zurückgeleitet wird, rufen wir das Zugriffstoken mit diesem Code ab

4.3. Foo-Komponente

Unsere dritte und letzte Komponente istFooComponent; Hier werden die Ressourcen vonFooangezeigt, die vom Ressourcenserver bezogen wurden:

import { Component } from '@angular/core';
import {AppService, Foo} from './app.service'

@Component({
  selector: 'foo-details',
  providers: [AppService],
  template: `

Foo Details

{{foo.id}}
{{foo.name}}
` }) 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'); } }

4.4. App-Service

Schauen wir uns nun dieAppService an:

import {Injectable} from '@angular/core';
import { Cookie } from 'ng2-cookies';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

export class Foo {
  constructor(
    public id: number,
    public name: string) { }
}

@Injectable()
export class AppService {
   public clientId = 'fooClientId';
   public redirectUri = 'http://localhost:8089/';

  constructor(
    private _http: HttpClient){}

  retrieveToken(code){
    let params = new URLSearchParams();
    params.append('grant_type','authorization_code');
    params.append('client_id', this.clientId);
    params.append('redirect_uri', this.redirectUri);
    params.append('code',code);

    let headers = new HttpHeaders({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Basic '+btoa(this.clientId+":secret")});
     this._http.post('http://localhost:8081/spring-security-oauth-server/oauth/token', params.toString(), { headers: headers })
    .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);
    console.log('Obtained Access token');
    window.location.href = 'http://localhost:8089';
  }

  getResource(resourceUrl) : Observable{
    var headers = new HttpHeaders({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Bearer '+Cookie.get('access_token')});
    return this._http.get(resourceUrl,{ headers: headers })
                   .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
  }

  checkCredentials(){
    return Cookie.check('access_token');
  }

  logout() {
    Cookie.delete('access_token');
    window.location.reload();
  }
}

Lassen Sie uns hier einen kurzen Überblick über unsere Implementierung geben:

  • checkCredentials(): um zu überprüfen, ob der Benutzer angemeldet ist

  • retrieveToken(): Zum Abrufen des Zugriffstokens mithilfe des Autorisierungscodes

  • saveToken(): Zum Speichern des Zugriffstokens in einem Cookie

  • getResource(): um Foo-Details anhand seiner ID abzurufen

  • logout(): Zum Löschen des Access Token-Cookies

5. Führen Sie die Anwendung aus

Um unsere Anwendung auszuführen und sicherzustellen, dass alles ordnungsgemäß funktioniert, müssen wir:

  • Führen Sie zunächst Authorization Server auf Port 8081 aus

  • Führen Sie dann den Resource Server auf Port 8082 aus

  • Führen Sie schließlich das Front-End aus

Wir müssen zuerst unsere App erstellen:

mvn clean install

Wechseln Sie dann in das Verzeichnis src / main / resources:

cd src/main/resources

Dann starte unsere App auf Port 8089:

npm start

6. Fazit

Wir haben gelernt, wie Sie mit Spring und Angular 6 einen einfachen Front-End-Client für den Authorization Code Flow erstellen.

Und wie immer ist der vollständige Quellcodeover on GitHub verfügbar.