2017-07-06 17 views
0

私はundertow、jersey、およびCDIを使用してセットアップした残りのエンドポイントでロールベースのアクセス制御を有効にしようとしています。次のように私は、サーブレットの配備を初期化します。Undertowサーブレットハンドラが既に認証された有効なSecurityContextをキークローンによって管理されています

DeploymentInfo servletBuilder = Servlets.deployment() 
    .setClassLoader(Main.class.getClassLoader()) 
    .setContextPath("/rest") 
    .setDeploymentName("sv.war") 
    .addListeners(listener(Listener.class)) 
    .setLoginConfig(new LoginConfig("KEYCLOAK", "some-realm")) 
    .setAuthorizationManager(auth) // my dummy for testing 
    .addServlets(servlet("jerseyServlet", ServletContainer.class) 
     .setLoadOnStartup(1) 
     .addInitParam("javax.ws.rs.Application", SystemViewApplication.class.getName()) 
     .addMapping("/api/*")); 

私はthis example codeに基づいkecloakの認証を可能にしました。

だから、私のサーバーは次のように開始されます。

二つの方法 sessionHandling()addSecurity()が、私は上記のリンクした例から持ち上げている
DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder); 
manager.deploy(); 

PathHandler path = Handlers.path(Handlers.resource(staticResources).setDirectoryListingEnabled(false).setWelcomeFiles("index.html")) 
    .addPrefixPath("/rest", manager.start()); 
Undertow server = Undertow.builder() 
    .addHttpListener(8087, "localhost") 
    .setHandler(sessionHandling(addSecurity(exchange -> { 
     final SecurityContext context = exchange.getSecurityContext(); 
     if (!context.isAuthenticated()) { 
     exchange.endExchange(); 
     return; 
     } 
     log.info("Authenticated: {} {} {}", context.getMechanismName(), context.getAuthenticatedAccount().getPrincipal().getName(), context.getAuthenticatedAccount().getRoles()); 
     // propagate the request 
     path.handleRequest(exchange); 
    }))) 
    .build(); 
server.start(); 

認証が動作し、強制的にログインし、Authenticated: ..ロギングラインが正しい詳細で出力されます。しかし、いったんサーブレット処理に当たれば、セキュリティコンテキスト(およびアカウント)は失われます。この呼び出しをたどったところ、パスに沿ったある時点で、ヌルアカウントを持つ新しいSecurityContextに置き換えられました。

私の質問 - キークローキ認証後に状態を伝播するいくつかの認証メカニズムがありますか、またはアンダートコードを修正できますか?SecurityContextで、渡されたコンテキストがすでに正しく認証されているその状態と移動? (サーブレットデプロイメントの認証が異なる可能性があるため、後者は正しいとは思えません)もしそうなら、サーブレットデプロイメントを接続して、すでにキークローキ認証が行われていることを確認する方法はありますか?

答えて

1

包みなさい誰もがkeycloakで適切にサーブレットを認証し、役割ベースの認証を使用する方法については、ここで見て、これはこれは純粋に注釈して、任意のXMLファイルを必要とせずに私のために働いた、ノート(私のために働いています。

まず次

またkeycloak.json"use-resource-role-mappings": trueを有効にしてください。RolesAllowedDynamicFeature.classサーブレットアプリケーション(あなたがResourceConfigを延長どこ)register()では、初期のSとサーブレットの展開をインスタンス化ecurityラッパー:sessionHandling(addSecurity(handler))は基本的にリンクされgithubのレポからコードです

DeploymentInfo servletBuilder = Servlets.deployment() 
    .setClassLoader(Main.class.getClassLoader()) 
    .setContextPath("/") 
    .setDeploymentName("sv.war") 
    .addListeners(listener(Listener.class)) 
    .setIdentityManager(idm) 
    .setSessionManagerFactory(new InMemorySessionManagerFactory()) 
    .setInitialSecurityWrapper(handler -> sessionHandling(addSecurity(handler))) 
    .setResourceManager(staticResources) 
    .addWelcomePage("index.html") 
    .addServlets(servlet("jerseyServlet", ServletContainer.class) 
     .setLoadOnStartup(1) 
     .addInitParam("javax.ws.rs.Application", SystemViewApplication.class.getName()) 
     .addMapping("/api/*")); 


DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder); 
manager.deploy(); 

Undertow server = Undertow.builder() 
    .addHttpListener(8087, "localhost") 
    .setHandler(Handlers.path(manager.start())) 
    .build(); 
server.start(); 

今keycloak経由で認証が機能し、あなたのような、残りのエンドポイントをCDIを注入している場合も、役割ベースの認証は、例えばので、動作します:限り、役割が設定されているよう

@RolesAllowed({"admin", "guest"}) 
@GET 
@Path("/{id}") 
public Response findById(@PathParam("id") @NotNull Integer id){ 
    // some method 
} 

キークローキングでは、うまくいくはずです。

関連する問題