フレームワーク | 株式会社Altus-Five / 株式会社Altus-Five は、技術力で勝負するシステム開発会社です。 Sun, 01 Jun 2025 17:43:38 +0000 ja hourly 1 https://wordpress.org/?v=6.8.2 /wp-content/uploads/2025/01/cropped-favicon-32x32.png フレームワーク | 株式会社Altus-Five / 32 32 TERASOLUNAの開発環境を30分で整備するスターターキット /blog/2017/12/07/terasoluna-starter-kit/ /blog/2017/12/07/terasoluna-starter-kit/#respond Wed, 06 Dec 2017 15:37:00 +0000 http://43.207.2.176/?p=334 TERASOLUNAについて TERASOLUNAは、Spring Frameworkを中心としたOSSの組み合わせで構成されたフレームワークです。開発ガイドも、公開されていて、とてもよくまとめられています。OSSの組み […]

The post TERASOLUNAの開発環境を30分で整備するスターターキット first appeared on 株式会社Altus-Five.

]]>
TERASOLUNAについて

TERASOLUNAは、Spring Frameworkを中心としたOSSの組み合わせで構成されたフレームワークです。
開発ガイドも、公開されていて、とてもよくまとめられています。
OSSの組み合わせということで、TERASOLUNAじゃないプロジェクトでも、こちらのガイドラインに記載されているベストプラクティスを何度となく参考にさせていただきました。

プロジェクトの立ち上げ

ここでいう”プロジェクトの立ち上げ”とは、実装フェーズの準備を指しています。
大まかに、やることは、こんな感じじゃないでしょうか?

  • 開発キットの準備
    開発チームのメンバーに、ローカルPCに開発環境を構築するための手順書を準備する。
  • リポジトリの準備
    ソースコードを管理するために、社内のGitlab等にリポジトリを準備する。
  • CI環境を準備
    社内の開発用サーバーにJenkinsNexusを準備する。
  • サンプル実装
    実装のお手本となるサンプル実装を作成する。
  • 規約や方針を整備
    コーディング規約や、開発方針(モデリングやトランザクション、CSRF、RPGなどの適用方法など)を整備する。

準備が悪いと、手戻りが多く、実装中に迷いがちになるので、開発効率に影響がでます。プロジェクトに先駆けて、できるだけ整備したいところです。
でも、上流工程が長引いて・・・などの理由で、準備に十分な時間をかけられないケースも、よくある話です。

私が、TERASOLUNAのプロジェクトを初めて手掛けたときは、JenkinsなどのCI環境の構築から、チーム内でCIが運用されるまでに、1カ月以上かかりました。実装フェーズが始まって、しばらくしてCI環境が稼働したため、Jenkinsからのエラーレポート対応で、本来のタスクが停滞したことを記憶しています。

スターターキット

プロジェクトの立ち上げ時の毎度毎度で、CI環境構築に1人月もかけてられません。
それならばとJenkins職人を育成するのも、どうかと思います。

そこで、TERASOLUNA用のCI環境の自動構築と、開発チームへの配布キットを自動生成するスターターキットを作りました。
https://github.com/altus5/terasoluna-starter-kit

~/bin/setup-ci.shを実行すると、ネットワーク内のサーバーにCI環境が作成されて、~/bin/create-development-kit.shの実行で、TERASOLUNAのブランクプロジェクトでリポジトリが作成され、配布する開発キットも同時に作成されます。

以前は、1カ月くらい準備に時間がかかっていたのに、2つのスクリプトで、わずか30分で実装フェーズの準備が整います。

ただ、このスターターキットは、もともと社内の開発用に作成したものなので、前提とする条件がエグイです。
実際には、プロジェクトに応じて、多少のアレンジが必要だと思いますが、スターターキットのひな形としては、使えるんじゃないでしょうか?

カスタマイズにお応えします。

さて、ひな形として使えるとは言え、そのカスタマイズに、1、2週間かかってしまったんでは、スターターキットの意味がありません。
貴社の貴重な”開発するための時間”を、その準備のために消費するのは、勿体ないです。
いっそ、スターターキットの制作を、弊社にご依頼されてみてはいかがでしょうか?低コスト短期間で、ご要望にお応えできると思います。
まずは、お問い合わせくださいませ。
貴社の開発環境とプロジェクトに合わせたカスタマイズ要件をお聞きし、お見積致します。
※TERASOLUNA以外のフレームワークも、対応可能です。

お問い合わせはこちらから

The post TERASOLUNAの開発環境を30分で整備するスターターキット first appeared on 株式会社Altus-Five.

]]>
/blog/2017/12/07/terasoluna-starter-kit/feed/ 0
Web Performerが出力したコードをSpring Boot化してみた /blog/2017/10/19/webperformer-spring-boot/ /blog/2017/10/19/webperformer-spring-boot/#respond Wed, 18 Oct 2017 16:06:00 +0000 http://43.207.2.176/?p=362 Web Performer とは Web Performer(以降WP)とは、超高速開発というジャンルに分類されている、 システムを自動生成するツールで、キヤノンITソリューションズさんが開発されています。弊社では、この […]

The post Web Performerが出力したコードをSpring Boot化してみた first appeared on 株式会社Altus-Five.

]]>
Web Performer とは

Web Performer(以降WP)とは、超高速開発というジャンルに分類されている、 システムを自動生成するツールで、キヤノンITソリューションズさんが開発されています。
弊社では、このツールを使って、システム開発のスピードアップにトライしています。
超高速開発と言われているツールには、他にも、GeneXus や、Wagby などがあります。
WP と GeneXus については、説明会に参加させていただき、Wagby については、 評価版を利用してみて、最終的に、WP を利用することにしました。

この3つのツールに共通しているのは、確かに自動生成してくれるのだけど、 すべての要件を100%自動生成できるわけではないということ。
やはり、複雑な処理は、追加で実装したり、外部に補助システムを構築したりして、100%じゃない部分を補完する必要があります。
自動生成して、時間を圧縮しても、この機能拡張の開発にもたついてしまうと、 せっかくのアドバンテージが無くなってしまうので、機能補完というか、機能拡張のやり方に、 それぞれのツールを有効活用するコツがあるように思います。

WPの場合は、拡張機能部分は、追加実装していく方式です。
自動生成されたコードは、修正しないで、機能拡張用のクラスを追加実装していきます。
その開発方法も、開発ガイドに準備されていて、わからない場合は、 サポートサイトが用意されているので、Googleで検索する代わりに、 そこに問い合わせをして、解決策を得る感じになります。
弊社が Web Performer を選択した理由の1つは、このサポートが手厚そうなところでした。

Spring Boot化

さて、WPを使った開発の中で、私たちで工夫してきたことが、いくつかあるので、ご紹介します。
記事タイトルにもしましたが、WPが生成したコードを Spring Boot 化する方法になります。

WPで出力されたコードは、Spring 4 に対応していますが、 Spring Boot ではありません。
弊社は、WPを使った開発もやっているけれど、スクラッチでの開発の方が、 開発機会としては多くて、Spring を使った開発だと、最近では、Spring Boot です。

弊社流のWPを活用した開発は、WPで典型的な実装を自動生成して、複雑なロジックの実装は、Spring Boot で実装するというやり方を採っています。 特にスクラッチの開発に慣れた人には、合ってるように思います。

※ここで紹介するやり方は、キヤノンITソリューションズさんでは、推奨していませんし、サポート対象外になると思うので、自己責任の元、行ってください。

mavenプロジェクトにする

WPを使うと、クラスのコンパイルまでやってくれるし、依存 jar なども、 自動的に配備してくれるので、mavenを使う必要はないのだけど、 Spring Boot化するには、mavenか、gradle プロジェクトにする必要があります。
弊社では、mavenプロジェクトにしました。

mavenを使うメリットは他にもあります。 WPは、インストールベースでライセンスが発生しますが、出力されたコードを使う分には、ライセンスが発生しません。
機能拡張の部分は、普通にJavaのクラスで実装するので、WPが無くても開発できます。 極端な話、WPでコード生成する作業を1台のPCで行って、生成されたコードをソース管理のリポジトリにコミットして、共有しておけば、他のPCでは、共有されたコードを使って、WPなしで機能拡張部分を開発することができます。
WPのインストールが不要なら、その分のライセンスも節約できます。

以下に pom.xml を作成する場合のポイントを整理してみましたので、参考にしてください。

プロジェクトの構成を分割する

弊社では、4つのプロジェクトに分けました

  1. 以下のプロジェクトのまとめ役としての親POMプロジェクト
  2. WPが生成するjspやWEB-INF配下とSpring Bootの構成ファイルをパッケージしたメインのwarプロジェクト
  3. WPが生成するjavaソースコードをまとめた jarプロジェクト
  4. 機能拡張部分の jarプロジェクト

上記の2と3は、1つでも良いのですが、4から3の中にある機能を利用する可能性を考慮するなら、分けておくと良いと思います。

WPが依存するjarを洗い出す

WPが利用しているjarを洗い出して、pom.xmlに追加します。

jarをリストアップ

WPでアプリケーションを生成したら、出力されたディレクトリにある、WEB-INF/lib の中にある jar をリストアップします。

pom.xml の dependency に追加

jarファイル名と、ファイル名にあるバージョン番号を手掛かりに、mvnrepositoryで検索して、pom.xml の dependency に追加します。

詳細がわからないjarの対応

jarファイル名だけでは、バージョン番号がわからないとか、mvnrepositoryで検索しても、見つからない jarがあったりします。もとより探すこと自体が面倒でもあります。
弊社では、groupIdを独自のものにして、mvnのローカルリポジトリに追加することで対応しました。可能なら、nexusなどのプライベートリポジトリを使った方がよいと思います。
例を示します。
commons-validator.jarというファイル名だけでは、バージョンがわかりません。ファイルサイズを手掛かりに、mvnrepositoryで検索すると、versionは、1.4であることがわかったのですが、それ自体面倒です。

  • 本来の正しい dependency
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.4</version>
</dependency>
  • 独自の dependency を作ってローカルリポジトリに登録してしまう
<dependency>
<groupId>jp.altus5.webperformer</groupId>
<artifactId>commons-validator</artifactId>
<version>2.1.1</version>
</dependency>

groupIdを jp.altus5.webperformer と他とは被らないものにして、versionは、WPのバージョンにしておくとよいと思います。
このままでは、jarが見つかりませんので、mvnコマンドで、ローカルリポジトリに追加します。

mvn install:install-file \
-Dfile=$webapp/WEB-INF/lib/commons-validator.jar \
-DgroupId=jp.altus5.webperformer \
-DartifactId=commons-validator \
-Dversion=2.1.1 \
-Dpackaging=jar \
-DgeneratePom=true \
-DcreateChecksum=true
Servletのバージョンを3.0にあわせる

Spring Bootのデフォルトのtomcatは、Servlet 3.0なので、3.0未満に依存した jarから、servlet-api を除外します。WP2.1.1では、axis2-jaxwsと、axis2-kernel、axis2-springの3つです。

<dependency>
  <groupId>org.apache.axis2</groupId>
  <artifactId>axis2-jaxws</artifactId>
  <exclusions>
    <exclusion>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

これは、Spring Boot化したら、WPの機能のうち、SOAPを使った機能が使えないかもしれないことを示唆しています。弊社では、SOAPを使わないので、その動作確認もしていませんが、もし、使いたい場合には、spring-boot-legacy の利用を検討するとよいと思います。

Spring Bootのプラグインや依存jarを追加する
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring BootでJSPを使えるようにする -->
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <scope>provided</scope>
</dependency>
Spring Bootを実行可能warとなるように設定する

Spring Bootは、実行可能なjarとしてビルドすることができますが、 WPが生成するコードは、jspが使われていて、Spring Bootでjspを使うには、 jarでは、無理で、warにビルドする必要があります。
こちらも、実行可能なwarとしてビルドできます。

jspやプロパティの文字コードをUTF-8に整える

この作業は無くても大丈夫ですが、一部のコードは、Windows-31jを文字コードとしたものが出力されます。
機能拡張の実装をするときに、WP以外の Eclipse や エディタでそのリソースを開くと文字化けして見辛いので、いっそ、文字コード変換をしておくとよいかもしれません。
弊社では、文字コード変換のための gulpタスクを作成して、nodejsで変換しています。

自動ビルドとnexusの利用

WP上で編集した各種定義ファイルを、リポジトリにプッシュしたら、コード生成からコンパイル、jar作成までを、自動ビルドするスクリプトがあると便利です。
特に、大きいプロジェクトになってくると、コンパイルに時間がかかるようになるので、メモリをたっぷり割り当てて、ビルド時間の最小化を試みるのもよいと思います。
弊社では、ビルドサーバーを設けて、WPのソースをプッシュしたら、ビルドサーバでビルドして、jarファイルをnexusのプライベートリポジトリにコミットして、 拡張機能の担当者に自動配布されるようにしています。

Spring Boot のコンフィグレーション

Spring Boot として実行するための main と、コンフィグレーションを実装します。 コンフィグレーションの内容は、WPが出力した web.xml をもとにします。

mainクラス

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

Web関連以外のコンフィグレーション

@Configuration
@ComponentScan(basePackages = {"jp.altus5.hoge", "jp.co.canon_soft.wp.runtime.webmvc.component"})
@EnableAutoConfiguration
public class AppConfig {
}

DBの構成なども、ここに追加して良いと思います。 弊社では、バッチ処理からもDBの構成を利用したいので、拡張ライブラリの方に、追加しました。

Web関連のコンフィグレーション

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }

    @Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
    public ServletRegistrationBean dispatcherServletRegistration() {
        ServletRegistrationBean registration = new ServletRegistrationBean(
                dispatcherServlet(), new String[]{"*.do"});
        registration
                .setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);

        return registration;
    }

    @Bean
    public ViewResolver setupViewResolver() {
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
        resolver.setViewClass(JstlView.class);
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addWebRequestInterceptor(new RequestInterceptor());
    }

    ・・・・

WPが出力したコードの所有権とか著作権は、弊社が保有するものの、WP自体はOSSではないので、 どこまで、コードを公開してよいのか、判断できないため、一部を抜粋して、問題なさそうな部分のみ掲載しています。

まとめ

以上、WPが出力したコードをSpring Boot化するポイントをご紹介しました。
もし、ご興味のある方がいらっしゃいましたら、お気軽にお問い合わせください。

The post Web Performerが出力したコードをSpring Boot化してみた first appeared on 株式会社Altus-Five.

]]>
/blog/2017/10/19/webperformer-spring-boot/feed/ 0
WEBサイト間のシステム連携をOAuth認証で保護する | LaravelアプリでのOAuthサーバの組み込み方法 /blog/2017/03/03/laravel-oauth-server/ /blog/2017/03/03/laravel-oauth-server/#respond Thu, 02 Mar 2017 17:35:00 +0000 http://43.207.2.176/?p=419 WEBサイト間でシステム連携を、WEB APIで実現する場合、第三者に勝手に利用されないように保護したい場合があると思います。対応策として、ネットワーク構成で防御する方法が真っ先に思い浮かびます。例えば、IPアドレスで制 […]

The post WEBサイト間のシステム連携をOAuth認証で保護する | LaravelアプリでのOAuthサーバの組み込み方法 first appeared on 株式会社Altus-Five.

]]>
WEBサイト間でシステム連携を、WEB APIで実現する場合、第三者に勝手に利用されないように保護したい場合があると思います。
対応策として、ネットワーク構成で防御する方法が真っ先に思い浮かびます。例えば、IPアドレスで制限する方法などです。その方法がとれるなら、簡単なので、そちらの方がよいでしょう。

この記事では、インフラ構成はそのままで、OAuth認証を使って安全に連携する方法をについて説明します。

Laravel5.3以降の場合は、laravel/passportが、公式パッケージとなったので、そちらを使ってください。 Laravel5.2以前は、プラグイン lucadegasperi/oauth2-server-laravel を使います。 どちらも、 league/oauth2-server が使われているので、内部は同じものです。

さて、laravel/passport については、これから、たくさんの記事が、出てくると思うので、そちらに、お任せして、 ここでは、Laravel5.2以前のLaravelを使っている”既存”システムに、OAuthサーバーを組み込む方法について、記載します。

本記事は、こちらの記事を参考にしました。合わせて読んでみてください。


OAuth2を使ったAPI実行の仕組み

oauth2-server-laravel の実装の前に、oauthでAPIを保護する仕組みについて、簡単に説明します。
サーバー間での認証の場合は、それほど複雑な手続きは発生しません。

前提

WEBサイトAと、WEBサイトBがあって、サイトBにあるAPIを、サイトAから利用したい場合を想定します。
ユーザーが、サイトAに訪問したときに、Aのサーバーサイドでは、サイトBのアクセストークンを取得して、そのアクセストークンを使って、サイトBのAPIを実行することで、第三者の不正利用を防ぎます。

ユーザー認証がないので、おそらく、実装の手間としては、一番簡単なOAuth認証かと思います。
手順は、API実行前にクライアントの認証を行うという、これだけです。

手順

  1. クライアント認証(アクセストークンの取得)
  2. API実行

それぞれの手順について、もう少し説明します。

手順(1) クライアント認証(アクセストークンの取得)

サイトAのサーバーサイドから、サイトBのアクセストークン取得APIを実行します。
client_id と client_secret をパラメータにして、認可されたクライアントであることを認証するわけですが、このパラメータが第三者の目に触れないように、サーバーサイドに実装します。 必要な設定値は次のとおりです。

パラメータ
grant_typeclient_credentials
client_id(例) AQ9c2NUJN6N4zLETk9NP8P762vnHdMHM
client_secret(例) We3Fkd6VMZ693msbLAWNDWdC4rPHwMy8
scopeなし

サーバー間の認証の場合、grant_type は、 client_credentials になります。
client_id と client_secret は、パスワード生成器などを使って、40文字以内の文字列を作成してください。この値は、あらかじめ、oauth2用に作成されるテーブルに、事前登録します。登録手順は、後述します。
scope は、この記事の説明では、1つの用途しかないので、scopeは、使いません。

参考
grant_type について、他にどのようなタイプがあるか、興味のある人は、以下に参考となるURLを上げておきますので、読んでみてください。

手順(2) API実行

上記で取得したアクセストークンを使って、サイトBのAPIを実行します。 APIは、oauth2で保護されていて、oauth2-serverによって、アクセストークンのチェックが行われます。


OAuth2サーバーの組み込み

OAuth2サーバーの組み込み方法を説明します。

oauth2は、Authorization Server と Resource Server の2つに役割が分かれていて、 それぞれ、別々のアプリとして、実装を分離することもできます。
この記事の説明では、同じアプリに実装します。

まずは、Authorization Server の実装です。

プラグインのインストールと設定

Laravelのバージョンと、プラグインのバージョンの対応は、こちらのページを見て、正しいバージョンのものをインストールしてください。4系と5系で違うようです。 https://github.com/lucadegasperi/oauth2-server-laravel/tree/master/docs#readme
以下は、laravel 5.2へのインストール手順です。

install

composerでプラグインを追加。

composer update
composer require lucadegasperi/oauth2-server-laravel:5.2.0

config/app.php の設定

次のように追加します。

'providers' => [
  ...
  LucaDegasperi\OAuth2Server\Storage\FluentStorageServiceProvider::class,
  LucaDegasperi\OAuth2Server\OAuth2ServerServiceProvider::class,
],

'aliases' => [
  ...
  'Authorizer' => LucaDegasperi\OAuth2Server\Facades\Authorizer::class,
],

app/Http/Kernel.php の設定

$middleware に次の行を追加。

\LucaDegasperi\OAuth2Server\Middleware\OAuthExceptionHandlerMiddleware::class,

$routeMiddleware に次のを追加。

'oauth' => \LucaDegasperi\OAuth2Server\Middleware\OAuthMiddleware::class,
'oauth-user' => \LucaDegasperi\OAuth2Server\Middleware\OAuthUserOwnerMiddleware::class,
'oauth-client' => \LucaDegasperi\OAuth2Server\Middleware\OAuthClientOwnerMiddleware::class,
'check-authorization-params' => \LucaDegasperi\OAuth2Server\Middleware\CheckAuthCodeRequestMiddleware::class,

もし、$middleware の配列に中に、 App\Http\Middleware\VerifyCsrfToken があったら、middlewareから削除して、middlewareから削除して、routeMiddleware に、次の行を追加。

'csrf' => App\Http\Middleware\VerifyCsrfToken::class,

VerifyCsrfToken については、他システムからRESTでアクセスされるとき、csrfのトークンチェックができないので、対象外にすることが目的です。
$routeMiddleware にするのではなく、VerifyCsrfToken.php の中に、除外パターンを書く方法でも、大丈夫です。
既存システムの構成に合わせて、変更してください。

マイグレーションと設定ファイルの出力

php artisan vendor:publish
php artisan migrate

マイグレーション中に”class not found”エラーが出る場合は、composer dump-autoloadを実行し、その後に再実行してください。

14個のテーブルが作成されて、 config/oauth2.php が作成されます。

設定ファイルの編集

システムの用途に合わせて、 config/oauth2.php を編集します。

前述のとおり、信頼されたシステム間での認証なので、client_credentials を実装します。

'grant_types' => [
    'client_credentials' => [
        'class' => '\League\OAuth2\Server\Grant\ClientCredentialsGrant',
        'access_token_ttl' => 3600
    ]
],

スコープも、今回は、使わないので、設定は、デフォルトのままで OK です。

クライアント情報の事前登録

アクセス元のクライアント情報となる client_id と client_secret をDBに登録します。
シーダークラスを作成して登録します。

php artisan make:seeder OauthClientsTableSeeder

作成されたコードに、クライアント情報を埋め込みます。

<?php

use Illuminate\Database\Seeder;

class OauthClientsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('oauth_clients')->insert([
            'id' => 'AQ9c2NUJN6N4zLETk9NP8P762vnHdMHM',
            'secret' => 'We3Fkd6VMZ693msbLAWNDWdC4rPHwMy8',
            'name' => 'サイトAの認可',
        ]);
    }
}

この値は、サイトAを識別するためのものです。もし、サイトCにも、利用を許可する場合は、サイトCのクライアント情報も追加します。

シーダーを実行して、DBに登録します。

php artisan db:seed --class=OauthClientsTableSeeder

アクセストークン取得のURLを routes に追加

app/Http/routes.phpに以下を追加します。例えば、こんな感じになります。

Route::group(['middleware' => ['web']], function () {
    ・・・
    Route::post('oauth/access_token', function() {
        return Response::json(Authorizer::issueAccessToken());
    });
});

routesの構成はアプリによって、さまざまなので、システムに合ったやり方で、実装してください。
アクセストークンの取得を、POSTリクエストにした場合、通常は、CSRFの対象となるように構成されていると思います。しかし、他システムからはダイレクトなアクセスになるので、 VerifyCsrfToken が機能しないように設定してください。
以下は、VerifyCsrfTokenに除外設定する場合の例です。

app\Http\Middleware\VerifyCsrfToken.php

app/Http/Kernel.php 

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        'oauth/access_token',
    ];
}

動作確認用のプログラムは、後述しますが、このAPIのレスポンス例は、次のようになります。

{
  "access_token": "O8kA3tFq8wmQHC9xNoJgluaLQGBEcQyidm8LKLWl",
  "token_type": "Bearer",
  "expires_in": 3600
}

以上が、Authorization Server の役割です。

エンドポイントの保護

ここから、Resource Server の役割です。
第三者の不正利用からAPIを保護するための実装です。

Route::group(['middleware' => ['oauth']], function () {
    Route::get('api/v1/hoge', 'Api\ApiController@hoge');
});

ここも、routesの構成はアプリによって、さまざまなので、既存システムに合ったやり方で、実装してください。
Kernel.php に実装した、’oauth’ が middleware として設定されていれば OK です。

oauthで保護されるエンドポイントには、取得したアクセストークンを付与することで、チェックが行われます。
アクセストークンの渡し方は、httpヘッダーに追加します。

Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia

もう1つ、oauth2-server のソースコードを読んでみたところ、クエリーパラメータでも渡せることがわかりました。その場合のパラメータ名は、 access_token です。(設定によって、変更可能です)
例)
https://example.com/api/v1/hoge?access_token=O8kA3tFq8wmQHC9xNoJgluaLQGBEcQyidm8LKLWl&param1=fuga&param2=piyo

動作確認のテスト用には、クエリーパラメータが楽ですね。
ちなみに、httpヘッダーでしか認識しないようにも、設定できそうです。 やり方は、 oauth2-server のソースコードかドキュメントを確認してみてください。

動作確認

次のテスト用のプログラムを作成すると、とっかかりの動作確認ができます。
サイトA相当が、 http://localhost/ でアクセスできるとして、 ドキュメントルートに、次の2つのテストプログラムを作成して配置してください。

テスト画面の表示用のプログラム
(site_a_init.php)

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
var GET_ACCESS_TOKEN_URL = 'site_a_proxy_access_token.php';

function getAccessToken() {
  return $.ajax({
    url: GET_ACCESS_TOKEN_URL,
    type: 'PUT',
    data: $('#access_token').serialize(),
    dataType: 'json'
  });
}

function onSubmitAccessToken() {
  getAccessToken()
    .then(function(oauthResponse) {
      $('input[name="access_token"]').val(oauthResponse.access_token);
    }, function(err) {
      console.log('getAccessToken err!');
      console.log(err);
      console.log(err.responseText);
    });
  return false;
}

$(function() {
  $('#access_token').submit(onSubmitAccessToken);
});
</script>
</head>

<body>
<h2>[access token]</h2>
<form id="access_token" method="post" action="site_a_proxy_access_token.php">
  <input type="submit" value="取得">
</form>

<h2>[API]</h2>
<form id="site_b_api" method="get" action="http://192.168.33.10/api/v1/hoge">
access_token <input type="text" name="access_token" value=""><br />
API パラメータ 1 <input type="text" name="param1" value="hoge"><br />
API パラメータ 2 <input type="text" name="param2" value="fuga"><br />
<input type="submit" value="実行">
</form>

</body>
</html>

サイトBのアクセストークンを取得するプログラム
(site_a_proxy_access_token.php)

<?php
define('SITE_B_ACCESS_TOKEN_URL', 'http://192.168.33.10/oauth/access_token');

$data = 'grant_type='     . 'client_credentials' .
        '&client_id='     . 'AQ9c2NUJN6N4zLETk9NP8P762vnHdMHM' .
        '&client_secret=' . 'We3Fkd6VMZ693msbLAWNDWdC4rPHwMy8';

$curl = curl_init(SITE_B_ACCESS_TOKEN_URL);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$accessTokenResponse = json_decode(curl_exec($curl));
curl_close($curl);
?>

テスト画面を表示します。
http://localhost/site_a_init.php

テストのやり方は、[access token] の「取得」ボタンを押すと、 アクセストークンが取得されて、[API]のところの access_token に反映されます。

次に、[API]の「実行」ボタンを押すと、APIが実行されます。

間違ったアクセストークンが拒否されることを確認するには、 access_token に異なる値を入れてみてください。


以上、WEBサイト間のシステム連携をOAuth認証で保護する方法をご紹介しました。

The post WEBサイト間のシステム連携をOAuth認証で保護する | LaravelアプリでのOAuthサーバの組み込み方法 first appeared on 株式会社Altus-Five.

]]>
/blog/2017/03/03/laravel-oauth-server/feed/ 0