Created 2020年2月18日23:30
Updated 2020年2月18日23:30
Categories
Java
Spring Boot
ProxyといえばNginxとかでやるのがお手軽な感じがしますが、事情がありJavaでプロキシを作る必要があったため調べてみました。
いろいろ調べて、Netflixが作っているSpring CloudのZuulというライブラリ?を使えばできそうということがわかりました。
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();
}
}
以上でプロキシの前処理としてヘッダーを付与したり編集できるようになりました。
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でプロキシは少々トリッキーな気もしますが、触った感じ結構いい感じのライブラリだったので安心して使えそうです。