2017-07-06 39 views
0

我試圖啓用基於角色的訪問控制,我已設置使用底池,球衣和CDI的休息終點。我初始化servlet部署如下:Undertow servlet處理程序丟失已經通過keycloak管理的身份驗證和有效的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/*")); 

我啓用kecloak認證基於this example code

所以,我的服務器啓動爲:

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(); 

如果這兩種方法sessionHandling()addSecurity()從例如舉起我上面鏈接。

驗證有效,我強制登錄,並且Authenticated: ..記錄行用正確的詳細信息打印出來。但是,一旦它遇到了servlet處理,安全上下文(和帳戶)就會丟失。我跟蹤了這​​個電話,我可以看到在路上的某個時刻,它被替換爲全新的SecurityContext,它有一個空賬戶。

現在我的問題 - 是否有一些身份驗證機制,我錯過了將在keycloak身份驗證之後傳播狀態,或者我可以只修復上游代碼,並且在SecurityContext中,如果傳入的上下文已經正確驗證,該狀態並繼續前進? (後者看起來不正確,我猜這是因爲這可能是servlet部署的不同身份驗證?)如果是這樣,是否有任何方法連接servlet部署以查看keycloak身份驗證已經發生?

回答

1

櫃面有人來就如何servlet的基於keycloak和使用角色的身份驗證正確驗證這裏尋找,這個工作對我來說(注意,這個工作對我來說沒有任何XML文件的要求,純粹與註解。

首先在servlet的應用程序(無論你擴展ResourceConfigregister()RolesAllowedDynamicFeature.class

而且在keycloak.json使"use-resource-role-mappings": true

接下來,最初的小號實例化servlet部署ecurity包裝:

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(); 

哪裏sessionHandling(addSecurity(handler))基本上是從鏈接GitHub庫的代碼。

現在認證通過keycloak會工作,也是基於角色的身份驗證將正常工作,因此,例如,如果你有一個CDI注入休息終點,如:

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

只要角色配置在keyclak中,它應該起作用。

相關問題