Spring Boot+Zuulでプロキシを構築して任意のヘッダーを渡す

Created 2020年2月18日23:30
Updated 2020年2月18日23:30
Categories Java Spring Boot

ProxyといえばNginxとかでやるのがお手軽な感じがしますが、事情がありJavaでプロキシを作る必要があったため調べてみました。

いろいろ調べて、Netflixが作っているSpring CloudのZuulというライブラリ?を使えばできそうということがわかりました。

環境

  • Java 8
  • Spring Framework 2.2.4

環境構築

Spring Initializrを使います。

DependenciesにSpring Security, Cloud Bootstrap, Zuul を追加します。

Zuulはメンテナンスモードらしく、機能追加などが行われていないようですね・・・

将来的にはEoLになりそうなので、ちゃんと使うなら後続ライブラリを探す必要がありそうです。

コード

まず、起動するクラスファイルに @EnableZuulProxy アノテーションをつけます。

これでプロキシとして動作させることができるようになります。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

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

続いて、 application.yml を編集します。

この設定では、受け取った全てのリクエストを別のページにプロキシすることができます。

zuul:
  routes:
    # ↓ここはなんでも良いです
    test:
      path: /**
      url: "http://another.endpoint.com/"

これで起動すればリダイレクトができるようになります。めっちゃ簡単ですね。

続いては目的のヘッダー編集をやってみたいと思います。

ヘッダーを編集

プロキシする前に処理を噛ませる場合はZuulFilterをBeanとして作成します。

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

public class AddHeaderFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() { return 1; }

    @Override
    public boolean shouldFilter() {  return true; }

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        try {
            // ここでヘッダーに値を設定
            context.addZuulRequestHeader("HeaderName", "HeaderValue");
        } catch (Exception e) {
            // エラー処理
        }
        return null;
    }
}

フィルターはBeanとして読み込みます。どこでも良いですが今回はメインクラスから読み込みました。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

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

    @Bean
    public AddHeaderFilter addHeaderFilter() {
        return new AddHeaderFilter();
    }
}

以上でプロキシの前処理としてヘッダーを付与したり編集できるようになりました。

Tips

OidcUser オブジェクトを取得

OAuth2の認証だけ受けて、ユーザー情報などを加工して流したいときに使えると思います(やって良いのか分かりませんが)。

Filterを次のように書き換えてください。

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();

        String newUser = "";
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            OidcUser user = (OidcUser) auth.getPrincipal();
            // 試しにユーザー名を加工してみる(認証項目を弄るのは危険なので基本的にやらないでください)
            newUser = user.getName() + "_authorized";
        }

        try {
            context.addZuulRequestHeader("UserName", newUser);
        } catch (Exception e) {
            // エラー処理
        }
        return null;

まとめ

思ったより設定が簡単で、RequestContextやSecurityContextHolderなどで色々取得でき自由度が高くて良いですね。

Javaでプロキシは少々トリッキーな気もしますが、触った感じ結構いい感じのライブラリだったので安心して使えそうです。

コメントを投稿

コメント