1概要

前回のSpring Cloudの記事で、リンクを追加しました:/tracing-services-with-zipkin[Zipkin]サポート。

この記事では、フロントエンドアプリケーションをスタックに追加します。

これまで、私たちはクラウドアプリケーションを構築するためにバックエンド全体に取り組んできました。しかし、UIがないのであれば、Webアプリケーションは何がいいのでしょうか。この記事では、1ページのアプリケーションをプロジェクトに統合することによって、この問題を解決します。

このアプリは

Angular



Bootstrap

を使って作成します。 Angular 4コードのスタイルは、Spring開発者にとって自然なクロスオーバーであるSpringアプリケーションをコーディングするのとよく似ています。フロントエンドのコードはAngularを使用しますが、この記事の内容は最小限の労力で任意のフロントエンドフレームワークに簡単に拡張できます。

この記事では、Angular 4アプリケーションを構築し、それをクラウドサービスに接続します。 SPAとSpring Securityの間でログインを統合する方法を説明します。また、AngularのHTTP通信サポートを使用してアプリケーションのデータにアクセスする方法も示します。

** 2ゲートウェイの変更点

フロントエンドを設定したら、フォームベースのログインに切り替えて、特権ユーザーにUIの安全な部分を使用します。これには、ゲートウェイセキュリティ設定を変更する必要があります。


2.1.

HttpSecurity


を更新する

まず、ゲートウェイの

SecurityConfig.java

クラスの

configure(HttpSecurity http)

メソッドを更新しましょう。

@Override
protected void configure(HttpSecurity http) {
    http
      .formLogin()
      .defaultSuccessUrl("/home/index.html", true)
      .and()
    .authorizeRequests()
      .antMatchers("/book-service/** ** ", "/rating-service/** ** ", "/login** ", "/")
      .permitAll()
      .antMatchers("/eureka/** ** ").hasRole("ADMIN")
      .anyRequest().authenticated()
      .and()
    .logout()
      .and()
    .csrf().disable();
}

まず、

/home/index.html

を指すようにデフォルトの成功URLを追加します。これが、Angularアプリが存在する場所になるためです。次に、

Eureka

リソース以外のゲートウェイを介した要求を許可するようにant matcherを設定します。これはすべてのセキュリティチェックをバックエンドサービスに委任します。

次に、ログインページへのデフォルトのリダイレクトで問題なく動作するため、ログアウト成功URLを削除しました。

** 2.2. プリンシパルエンドポイントを追加+

**

次に、認証されたユーザーを返すためのエンドポイントを追加しましょう。これは、Angularアプリでログインしてユーザーの役割を識別するために使用されます。これは私達が彼らが私達のサイトで彼らができることができる行動を制御するのを助けるでしょう。

ゲートウェイプロジェクトで、

AuthenticationController

クラスを追加します。

@RestController
public class AuthenticationController {

    @GetMapping("/me")
    public Principal getMyUser(Principal principal) {
        return principal;
    }
}

コントローラは、現在ログインしているユーザオブジェクトを呼び出し元に返します。これにより、Angularアプリを制御するために必要なすべての情報が得られます。


2.3. ランディングページを追加

ユーザーがアプリケーションのルートにアクセスしたときに何かが見えるように、非常に単純なランディングページを追加しましょう。


src/main/resources/staticに、ログインページへのリンクを含む

index.html__ファイルを追加しましょう。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Book Rater Landing</title>
</head>
<body>
    <h1>Book Rater</h1>
    <p>So many great things about the books</p>
    <a href="/login">Login</a>
</body>
</html>


3 Angular CLIとスタータープロジェクト

新しいAngularプロジェクトを始める前に、https://nodejs.org/en/download/[Node.js and npm]の最新版をインストールしてください。


3.1. Angular CLI

をインストールする

はじめに、Angularコマンドラインインターフェイスをダウンロードしてインストールするために

npm

を使用する必要があります。端末を開いて実行します。

npm install -g @angular/cli

これはCLIをグローバルにダウンロードしてインストールします。


3.2. 新しいプロジェクトをインストールする

まだターミナルにいる間に、ゲートウェイプロジェクトにナビゲートし、gateway/src/mainフォルダに行きます。 「angular」という名前のディレクトリを作成し、それに移動します。ここから実行:

ng new ui

我慢して; CLIが新しいプロジェクトを設定し、すべてのJavaScript依存関係をnpmでダウンロードこのプロセスに何分もかかることも珍しくありません。


ng

コマンドはAngular CLIのショートカットで、

new

パラメータはそのCLIに新しいプロジェクトを作成するように指示し、

ui

コマンドはプロジェクトに名前を付けます。


3.3. プロジェクトを実行する


new

コマンドが完了したら。作成した

ui

フォルダーに移動して実行します。

ng serve

プロジェクトがビルドされたら、http://localhost:4200に移動します。これがブラウザに表示されるはずです。

リンク:/uploads/angular2-start-1.png%20413w[]

おめでとうございます。 Angularアプリを作成しました。


3.4. ブートストラップをインストールする

ブートストラップをインストールするのにnpmを使用しましょう。 uiディレクトリからこのコマンドを実行します。

npm install[email protected]--save

これにより、ブートストラップがnode__modulesフォルダにダウンロードされます。


ui

ディレクトリで、

.angular-cli.json

ファイルを開きます。これは私たちのプロジェクトに関するいくつかのプロパティを設定するファイルです。

apps> styles

プロパティを見つけて、Bootstrap CSSクラスのファイルの場所を追加します。

"styles":[    "styles.css",
    "../node__modules/bootstrap/dist/css/bootstrap.min.css"],

これにより、Angularはプロジェクトでビルドされたコンパイル済みCSSファイルにBootstrapを含めるようになります。


3.5. ビルド出力ディレクトリを設定する

次に、Springブートアプリケーションがそれらを処理できるように、Angularにビルドファイルの保存場所を指定する必要があります。 Spring Bootはresourcesフォルダ内の2つの場所からファイルを提供することができます。

  • src/main/resources/static

  • src/main/resource/public

Eureka用のリソースを提供するために既に静的フォルダを使用しており、Angularはビルドが実行されるたびにこのフォルダを削除するので、Angularアプリをパブリックフォルダにビルドしましょう。


.angular-cli.json

ファイルをもう一度開き、

apps> outDir

プロパティを見つけます。その

stringを更新します。

"outDir": "../../resources/static/home",

Angularプロジェクトがsrc/main/angular/uiにある場合は、src/main/resources/publicフォルダにビルドされます。アプリが別のフォルダにある場合は、この文字列を変更して場所を正しく設定する必要があります。


3.6. Maven

でビルドを自動化する

最後に、コードをコンパイルするときに実行する自動ビルドを設定します。このAntタスクは、「mvn compile」が実行されるたびにAngular CLIビルドタスクを実行します。この手順をゲートウェイのPOM.xmlに追加して、コンパイルするたびに最新のuiの変更が反映されるようにします。

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <configuration>
                <tasks>
                    <exec executable="cmd" osfamily="windows"
                      dir="${project.basedir}/src/main/angular/ui">
                        <arg value="/c"/>
                        <arg value="ng"/>
                        <arg value="build"/>
                    </exec>
                    <exec executable="/bin/sh" osfamily="mac"
                      dir="${project.basedir}/src/main/angular/ui">
                        <arg value="-c"/>
                        <arg value="ng build"/>
                    </exec>
                </tasks>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>

この設定ではAngular CLIがクラスパスで利用可能である必要があることに注意してください。このスクリプトを依存関係のない環境にプッシュすると、ビルドが失敗します。

それでは、Angularアプリケーションの構築を始めましょう。


4角

チュートリアルのこのセクションでは、ページ内に認証メカニズムを構築します。基本認証を使用し、それを機能させるために単純なフローに従います。

ユーザーは自分のユーザー名とパスワードを入力できるログインフォームを持っています。

次に、その資格情報を使用してbase64認証トークンを作成し、

“/me”

エンドポイントを要求します。エンドポイントは、このユーザーの役割を含む

Principal

オブジェクトを返します。

最後に、クレデンシャルとプリンシパルを以降のリクエストで使用するクライアントに保存します。

これがどのように行われるのかを見てみましょう。


4.1. テンプレート

ゲートウェイプロジェクトで、

src/main/angular/ui/src/app

に移動し、

app.component.html

ファイルを開きます。これはAngularが最初にロードしたテンプレートで、ログイン後にユーザーがアクセスする場所になります。

ここでは、ログインフォームを含むナビゲーションバーを表示するためのコードを追加します。

<nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
    <button class="navbar-toggler navbar-toggler-right" type="button"
      data-toggle="collapse" data-target="#navbarCollapse"
      aria-controls="navbarCollapse" aria-expanded="false"
      aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
    </button>
    <a class="navbar-brand" href="#">Book Rater
        <span ** ngIf="principal.isAdmin()">Admin</span></a>
    <div class="collapse navbar-collapse" id="navbarCollapse">
    <ul class="navbar-nav mr-auto">
    </ul>
    <button ** ngIf="principal.authenticated" type="button"
      class="btn btn-link" (click)="onLogout()">Logout</button>
    </div>
</nav>

<div class="jumbotron">
    <div class="container">
        <h1>Book Rater App</h1>
        <p ** ngIf="!principal.authenticated" class="lead">
        Anyone can view the books.
        </p>
        <p ** ngIf="principal.authenticated && !principal.isAdmin()" class="lead">
        Users can view and create ratings</p>
        <p ** ngIf="principal.isAdmin()"  class="lead">Admins can do anything!</p>
    </div>
</div>

このコードはBootstrapクラスでナビゲーションバーを設定します。バーに埋め込まれているのはインラインログインフォームです。 Angularはこのマークアップを使用してJavaScriptと動的に対話して、ページのさまざまな部分をレンダリングし、フォーム送信などを制御します。


(ngSubmit)=” onLogin(f)”

のようなステートメントは、フォームが送信されたときにメソッド“ onLogin(f)”

を呼び出し、そのフォームをその関数に渡すことを単に示しています。

jumbotron__ div内には、主要オブジェクトの状態に応じて動的に表示される段落タグがあります。

次に、このテンプレートをサポートするTypescriptファイルをコーディングしましょう。

** 4.2. タイプスクリプト+

**

同じディレクトリからapp.component.tsファイルを開きます。このファイルでは、テンプレート関数を作成するために必要なすべてのtypescriptプロパティとメソッドを追加します。

import {Component} from "@angular/core";
import {Principal} from "./principal";
import {Response} from "@angular/http";
import {Book} from "./book";
import {HttpService} from "./http.service";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls:['./app.component.css']})
export class AppComponent {
    selectedBook: Book = null;
    principal: Principal = new Principal(false,[]);
    loginFailed: boolean = false;

    constructor(private httpService: HttpService){}

    ngOnInit(): void {
        this.httpService.me()
          .subscribe((response: Response) => {
              let principalJson = response.json();
              this.principal = new Principal(principalJson.authenticated,
              principalJson.authorities);
          }, (error) => {
              console.log(error);
        });
    }

    onLogout() {
        this.httpService.logout()
          .subscribe((response: Response) => {
              if (response.status === 200) {
                  this.loginFailed = false;
                  this.principal = new Principal(false,[]);
                  window.location.replace(response.url);
              }
           }, (error) => {
               console.log(error);
       });
    }
}

このクラスは、Angularライフサイクルメソッド

ngOnInit()

にフックします。このメソッドでは、

/me

エンドポイントを呼び出して、ユーザーの現在の役割と状態を取得します。これにより、メインページに表示される内容が決まります。このメソッドは、このコンポーネントが作成されるたびに起動されます。これは、ユーザーのプロパティでアプリのアクセス許可を確認するのに最適なタイミングです。

ユーザーをログアウトさせてこのページの状態を元の設定に戻す

onLogout()

メソッドもあります。

しかしここではいくらかの魔法が起こっています。コンストラクタで宣言されている

httpService

プロパティAngularは実行時にこのプロパティをクラスに注入します。 Angularは、Springと同じように、サービスクラスのシングルトンインスタンスを管理し、コンストラクタインジェクションを使用してそれらを注入します。

次に、

HttpService

クラスを定義する必要があります。


4.3.

HttpService


同じディレクトリに

“ http.service.ts”

という名前のファイルを作成します。このファイルにログインおよびログアウトメソッドをサポートするためにこのコードを追加して下さい:

import {Injectable} from "@angular/core";
import {Observable} from "rxjs";
import {Response, Http, Headers, RequestOptions} from "@angular/http";
import {Book} from "./book";
import {Rating} from "./rating";

@Injectable()
export class HttpService {

    constructor(private http: Http) { }

    me(): Observable<Response> {
        return this.http.get("/me", this.makeOptions())
    }

    logout(): Observable<Response> {
        return this.http.post("/logout", '', this.makeOptions())
    }

    private makeOptions(): RequestOptions {
        let headers = new Headers({'Content-Type': 'application/json'});
        return new RequestOptions({headers: headers});
    }
}

このクラスでは、AngularのDI構文を使用して別の依存関係を注入しています。今回は

Http

クラスです。このクラスはすべてのHTTP通信を処理し、フレームワークによって提供されます。

これらのメソッドはそれぞれ、AngularのHTTPライブラリを使用してHTTPリクエストを実行します。

各要求は、ヘッダーのコンテンツタイプも指定します。

これで、依存性注入システムに

HttpService

を登録するために、もう1つ必要なことがあります。

app.module.ts

ファイルを開き、providerプロパティを見つけます。その配列に

HttpService

を追加します。結果は次のようになります。

providers:[HttpService],


4.4. 主体を追加

次に、タイプスクリプトコードにPrincipal DTOオブジェクトを追加しましょう。同じディレクトリに「principal.ts」というファイルを追加し、次のコードを追加します。

export class Principal {
    public authenticated: boolean;
    public authorities: Authority[]=[];
    public credentials: any;

    constructor(authenticated: boolean, authorities: any[], credentials: any) {
        this.authenticated = authenticated;
        authorities.map(
          auth => this.authorities.push(new Authority(auth.authority)))
        this.credentials = credentials;
  }

    isAdmin() {
        return this.authorities.some(
          (auth: Authority) => auth.authority.indexOf('ADMIN') > -1)
    }
}

export class Authority {
    public authority: String;

    constructor(authority: String) {
        this.authority = authority;
    }
}


Principal

クラスと

Authority

クラスを追加しました。これらは2つのDTOクラスで、SpringアプリケーションのPOJOとよく似ています。そのため、これらのクラスを角度付きでDIシステムに登録する必要はありません。

次に、未知のリクエストをアプリケーションのルートにリダイレクトするようにリダイレクトルールを設定しましょう。

** 4.5. 404取り扱い

**

ゲートウェイサービスのJavaコードに戻りましょう。

GatewayApplication

クラスが存在する場所に、

ErrorPageConfig

という新しいクラスを追加します。

@Component
public class ErrorPageConfig implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.NOT__FOUND,
          "/home/index.html"));
    }

}

このクラスは404応答を識別し、ユーザーを

“/home/index.html”

にリダイレクトします。単一ページのアプリでは、クライアントがすべてのナビゲーション可能なルートを処理する必要があるため、これが専用リソースに送られないすべてのトラフィックを処理する方法です。

これで、このアプリを起動して、構築したものを確認する準備が整いました。


4.6. ビルドと表示

ゲートウェイフォルダから「

mvn compile

」を実行します。これでJavaソースがコンパイルされ、Angularアプリがパブリックフォルダにビルドされます。他のクラウドアプリケーション、

config



discovery

、および

zipkin

を起動しましょう。その後、ゲートウェイプロジェクトを実行します。サービスが開始したら、


http://localhost:8080


に移動してアプリを表示します。このようなものが見えるはずです。

リンク:/uploads/ng2-landing-1.png%20560w[]

次に、ログインページへのリンクをたどりましょう。

リンク:/uploads/ng2-login-1.png%20491w[]

ユーザー/パスワード資格情報を使用してログインします。 「ログイン」をクリックすると、シングルページアプリケーションがロードされる/home/index.htmlにリダイレクトされます。

リンク:/uploads/ng2-user-1-3-1024×155.png%201024w[]


jumbotron

は、ユーザーとしてログインしていることを示しているようです。

右上のリンクをクリックしてログアウトし、今度は

admin/admin

認証情報を使用してログインします。

リンク:/uploads/ng2-admin-1-1-1024×167.png%201024w[]

いいね!これで、管理者としてログインしました。


5結論

この記事では、1ページのアプリをクラウドシステムに簡単に統合できることを説明しました。私たちは最新のフレームワークを取り、実用的なセキュリティ設定をアプリケーションに統合しました。

これらの例を使用して、

book-service

または

rating-service

を呼び出すためのコードを書いてみてください。 HTTP呼び出しとテンプレートへのデータの配線の例があるので、これは比較的簡単なはずです。

このサイトの残りの部分がどのように構築されているかを知りたい場合は、ソースコードhttps://github.com/eugenp/tutorials/tree/master/spring-cloud/spring-cloud-bootstrap[over onをご覧ください。 Github]。