2

はじめに、要件:

現在、Spring REST API と通信する AngularJS を使用してシングル ページ アプリケーションを作成しています。セキュリティ上の理由から、API へのすべてのリクエストをプロキシし、ユーザーが認証されていることを確認する zuul を使用してリバース プロキシをセットアップしたいと考えています。また、ユーザーが認証されていない場合は、OpenAM インスタンス (OAuth 2 承認サーバーとして機能する) にリダイレクトする必要があります。ユーザーが認証されている場合、少なくともユーザーの LDAP グループを含むヘッダーに Json Web トークン (JWT) を含むリクエストを API に転送する必要があります。

要するに、このチュートリアルのソリューションに似た API ゲートウェイのようなものが欲しいと思います: https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-セキュリティ-パート-v

現状

次の構成で Spring Cloud Security と Zuul をセットアップします。

server:
  port: 9000
spring:
  oauth2:
    sso:
      home:
        secure: false
        path: /,/**/*.html
    client:
      accessTokenUri: http://openam.example.org:8080/OpenAMTest/oauth2/access_token
      userAuthorizationUri: http://openam.example.org:8080/OpenAMTest/oauth2/authorize
      clientId: bearer-client
      clientSecret: clientsecret
      scope: openid profile
    resource:
      userInfoUri: http://openam.example.org:8080/OpenAMTest/oauth2/userinfo
zuul:
  routes:
    exampleApp:
      path: /example-application/**
      url: http://openam.example.org:8081/example-application

Application クラスは次のようになります。

@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class TestZuulProxy extends SpringBootServletInitializer {

public static void main(String[] args){

    SpringApplication.run(TestZuulProxy.class, args);
}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(applicationClass);
}

private static Class<TestZuulProxy> applicationClass = TestZuulProxy.class;

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter {

    @Override
    public void match(RequestMatchers matchers) {
        matchers.anyRequest();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/index.html", "/home.html", "/")
                .permitAll().anyRequest().authenticated().and().csrf()
                .csrfTokenRepository(csrfTokenRepository()).and()
                .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);

    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository;
    }

    public class CsrfHeaderFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                    .getName());
            if (csrf != null) {
                Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                String token = csrf.getToken();
                if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
                    cookie = new Cookie("XSRF-TOKEN", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
            filterChain.doFilter(request, response);
        }
    }
}
}

「example-application」に移動すると、OpenAM 認証ログイン画面に転送されます。資格情報を入力すると、「example-application」にアクセスできます。ゲートウェイ サービスのコンソール ログ:

2015-06-22 17:14:10.911  INFO 6964 --- [nio-9000-exec-3] o.s.c.s.o.r.UserInfoTokenServices        : Getting user info from: http://openam.example.org:8080/OpenAMTest/oauth2/userinfo
2015-06-22 17:14:10.953  INFO 6964 --- [nio-9000-exec-3] o.s.b.a.audit.listener.AuditListener     : AuditEvent [timestamp=Mon Jun 22 17:14:10 CEST 2015, principal=Aaccf Amar, type=AUTHENTICATION_SUCCESS, data={details=remoteAddress=0:0:0:0:0:0:0:1, sessionId=<SESSION>, tokenType=BearertokenValue=<TOKEN>}]

Zuul フィルターによって読み取られる HTTP ヘッダー:

authorization --- Bearer c2b75b5a-c026-4e07-b8b9-81e9162c9277
x-forwarded-host --- localhost:9000
x-forwarded-prefix --- /example-application

だから何かがうまくいく!REST-API に転送されるアクセス トークンがあります。

問題

1) このソリューションは私の要件を実際には満たしていません。なぜなら、REST API で OpenAM のトークン エンドポイントを呼び出させたくないからです。必要なクレームを含む JWT がヘッダーの API に渡されるようにします。ゲートウェイ (Zuul フィルターなど) で JWT を手動で作成する必要がありますか、それとも別の解決策がありますか?

2) 上記のソリューションでは、アクセス トークンの有効期限が切れると、Zuul は引き続き API に転送します。どうしてこれなの?Spring Oauth2 はアクセストークンの有効期限が切れているかどうかをチェックしませんか? どうすればそれを実装できますか?

3) application.yml で tokenInfoUri も構成しようとしましたが、OpenAM が tokeninfo-Endpoint で GET 要求を予期していると思われるため、"405 Method Not Allowed" 例外が発生します。これをどうにかカスタマイズできますか?リクエストを変更するには、どのクラスをオーバーライド/カスタマイズする必要がありますか。

アドバイス、アイデア、解決策があれば教えてください!

ありがとうございました!

4

1 に答える 1

0

アプリケーションで JWT を使用する場合は、OpenAM を OpenID Connect プロバイダー (OpenAM 12.0 以降) として構成します。ユーザーが認証されると、OpenAM はユーザーに関する多数のクレームを含む JWT を発行します。SPA は、サービス層への要求でそれを渡すことができます。

ゲートウェイでユーザー セッションに AuthN/AuthZ を強制する場合は、ForgeRock の OpenIG などを使用できます。これは、ポリシー実施ポイントとして機能し、JWT トークンをイントロスペクトする機能を備えています。

于 2015-06-23T13:29:33.163 に答える