Help us understand the problem. What is going on with this article?

Spring Cloudでマイクロサービス

More than 3 years have passed since last update.

Spring cloud を使用してシンプルなマイクロサービスを構成します。ログインにはOAuth2を使用してGoogleアカウントでログインできるようにします。ソースは https://github.com/jun-1/spring-cloud-microservices

全体構成

ブラウザ等のクライアントとの対話やログイン処理はweb-serviceが行いbackend-serviceに各種機能を要求します。この際discovery-serviceにサービスを登録することで各サービスがお互いを見つけられるようにします。

image

discovery-seriviceの実装

@EnableEurekaServerアノテーションを付けたspring-bootアプリケーションを作成するだけでサービスレジストリとしてEurekaサーバーが実装できます。
また http://localhost:8761 からステータスを確認できます。

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class DeiscoveryServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(DeiscoveryServiceApplication.class, args);
    }
}

ポート番号と自分自身をレジストリに登録しないため設定をします。

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
server:
  port: 8761

web-serviceの実装

はじめにOAuthで使用するクライアントIDとクライアントシークレットを取得します。

Googleの認証情報作成

https://console.developers.google.com で認証情報を作成します。

image

[認証情報]から[プロジェクトを作成]をクリックしプロジェクトを作成します。

image

OAuthクライアントIDを選択し認証情報を作成します。(OAuth同意画面を作成していない場合は作成しておきます)

image

localhostで動かす場合は[その他]を選択して[作成]ボタンをクリックすると、OAuthクライアントのクライアントIDとクライアントシークレットが取得できます。

アプリケーションの実装

web-serviceの役割はクライアントとの対話とログイン、それからbackend-serviceに対するリバースプロキシです。

@EnableZuulProxyをつけることでZuulを使用してCORSと認証の懸念事項を個別に管理することなくリバースプロキシとして動作させることができます。
@EnableOAuth2SsoをつけることでOAuth2に基づくシングルサインオンが実現できます。

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableEurekaClient
@EnableZuulProxy
@EnableOAuth2Sso
@SpringBootApplication
public class WebServiceApplication extends WebSecurityConfigurerAdapter{

    public static void main(String[] args) {
        SpringApplication.run(WebServiceApplication.class, args);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "index.html").permitAll()
            .anyRequest().authenticated();
    }
}

configure()ではindex.html以外のURLへのアクセスには認証が必要と設定しています。
次はweb-serviceの設定です。

spring:
  application:
    name: web-service
eureka:
  client:
    service-url: 
      defaultZone: http://localhost:8761/eureka
zuul:
  ignored-services: '*'
  routes:
    backend-service: 'api/**'
security:
  oauth2:
    resource:
      user-info-uri: https://www.googleapis.com/oauth2/v1/userinfo
    client:
      access-token-uri: https://accounts.google.com/o/oauth2/token
      user-authorization-uri: https://accounts.google.com/o/oauth2/auth
      client-id: ${clientId}
      client-secret: ${clientSecret}
      grant-type: code
      scope: profile

spring.application.nameで設定した名前でEurekaサーバーにサービスが登録されます。
登録先のサーバーはeureka.client.service.url.defaultZoneで指定します。

zuulの設定でapi/**へのリクエストをbackend-serviceに転送するようにしています。
ここでは転送先にEurekaサーバーに登録したサービス名を使用できます。

securityの設定はOAuth2クライアントの設定です。ここで先ほど取得したクライアントIDとクライアントシークレットを使用します。

backend-service

backend-serviceはOAuth2のクライアントでありリソースサーバーとして実装しています。

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@EnableEurekaClient
@EnableOAuth2Client
@EnableResourceServer
@SpringBootApplication
public class BackendServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(BackendServiceApplication.class, args);
    }
}

以下は'Hello'の文字列を返すだけのコントローラーですが、OAuth2の認証がなければアクセスできないようになります。web-service経由でアクセスした場合はZuul Proxyが認証トークンをリレーしてくれるためweb-serviceでログインしていれば/api/helloで呼び出すことが可能です。

package demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BackendController {

    @RequestMapping("/hello")
    public String hello(){
        return "Hello";
    }
}

また、以下のようにOAuth2RestTemplateを使用すると、他のサービスとRest通信を簡単に行うことができます。

    @Bean
    @LoadBalanced
    public OAuth2RestTemplate oAuth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context){
        return new OAuth2RestTemplate(resource, context);
    }
jun-1
genuine
確かな技術力と誠実な人間力、ユーザー目線の業務スキルで本当に必要とされるシステムを構築する会社です。
https://genuine-pt.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした