2015-10-18 175 views
1

我玩Wildfly-9.0.1.FinalJAAS,但我並沒有這麼多的樂趣..我實現我的自定義登錄模塊:Wildfly和JAAS登錄模塊

public class MongoLoginModule implements LoginModule { 

@Inject 
protected MongoDB mongoDb; 
protected Subject subject; 
protected Principal identity; 
protected boolean loginOk; 

private CallbackHandler callbackHandler; 
private Map sharedState; 
private Map options; 

private Logger log = LoggerFactory.getLogger(MongoLoginModule.class); 

public boolean abort() throws LoginException { 
    log.info("abort!"); 
    subject = null; 
    return true; 
} 

public boolean commit() throws LoginException { 
    // TODO Auto-generated method stub 
    log.info("commit!"); 
    if(loginOk) { 
     UserGroup userGroup = new UserGroup("Roles"); 
     userGroup.addMember(new RolePrincipal("userA")); 
     subject.getPrincipals().add(userGroup); 
     subject.getPublicCredentials().add(userGroup); 
     return true; 
    } 
    return false; 
} 

public void initialize(Subject subject, CallbackHandler callbackHandler, 
     Map<String, ?> sharedState, Map<String, ?> options) { 
    log.info("Initializing MongoLoginModule."); 
    this.subject = subject; 
    this.callbackHandler = callbackHandler; 
    this.sharedState = sharedState; 
    this.options = options; 
} 

public boolean login() throws LoginException { 
    log.info("login requested."); 
    NameCallback nameCallback = new NameCallback("username:"); 
    PasswordCallback passwordCallback = new PasswordCallback("password:", false); 
    try { 
     callbackHandler.handle(new Callback[]{nameCallback, passwordCallback}); 
     String username = nameCallback.getName(); 
     String password = new String(passwordCallback.getPassword()); 
     log.info("check credentials for: "+username); 
     if(username.equals("jim") && password.equals("jim")) { 
      loginOk = true; 
      identity = new UserPrincipal(username); 
      subject.getPrincipals().add(identity); 
      subject.getPublicCredentials().add(identity); 
      return true; 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedCallbackException e) { 
     e.printStackTrace(); 
    } 

    return false; 
} 

public boolean logout() throws LoginException { 
    if(subject != null && identity != null) { 
     subject.getPrincipals().remove(identity); 
     return true; 
    } 
    return false; 
} 

public Document getUserByName(String userName) { 
    FindIterable<Document> results = mongoDb.getCollection().find(new Document("username", userName)); 
    return results.iterator().next(); 
} 

public void getRoles() { 
//  FindIterable<Document> results = mongoDb.getCollection().find(new Document("username", userName)); 
//  results.iterator().next().get 
} 

它並不完美,但它足夠多的現在。這個純粹的JAAS登錄模塊是我的Wildfly中的一個模塊。我這樣配置安全域:

<security-domain name="MongoLoginRealm" cache-type="default"> 
    <authentication> 
     <login-module code="it.bytebear.jaas.mongo.module.MongoLoginModule" flag="required" module="login.mongodb"> 
      <module-option name="mongodb.uri" value="mongodb://localhost:21017/test?collection"/> 
     </login-module> 
    </authentication> 
</security-domain> 

我實現了一些REST風格的web服務來做一些測試。我只是張貼了相關代碼:

... 

@POST 
@Path("/login") 
@PermitAll 
@Consumes(MediaType.APPLICATION_JSON) 
// @Consumes("application/x-authc-username-password+json") 
public Response login(User userCredentials) { 
    log.info("logging in."); 
    try { 
     MongoModuleCallbackHandler handler = new MongoModuleCallbackHandler(); 
     handler.setUsername(userCredentials.getUserName()); 
     handler.setPassword(userCredentials.getPassword().toCharArray()); 
     LoginContext loginContext = new LoginContext("MongoLoginRealm", handler); 
     loginContext.login(); 
     Subject subject = loginContext.getSubject(); 
     List<String> roles = new ArrayList<String>(); 
     for (Principal p : subject.getPrincipals()) { 
      roles.add(p.getName()); 
     } 
     userCredentials.setRoles((String[]) roles.toArray()); 
     return Response.ok().entity(userCredentials) 
       .type(MediaType.APPLICATION_JSON_TYPE).build(); 
    } catch (Exception e) { 
     log.error("login fails.", e); 
     return Response.status(Status.FORBIDDEN).entity("Not logged") 
       .type(MediaType.APPLICATION_JSON_TYPE).build(); 
    } 
} 
... 

web.xmlauth-methodBASICrealm-nameMongoLoginRealm,在jboss-web.xml和實例LoginContext時使用的相同。當我調用login方法,我得到這個異常:

22:39:49,421 ERROR [it.bytebear.web.mongo.UserServices] (default task-1) login fails.: javax.security.auth.login.LoginException: impossibile trovare la classe Login 
Module: it.bytebear.jaas.mongo.module.MongoLoginModule from [Module "deployment.MongoWebTest.war:main" from Service Module Loader] 
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:822) 
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203) 
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698) 
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695) 
    at javax.security.auth.login.LoginContext.login(LoginContext.java:594) 
    at it.bytebear.web.mongo.UserServices.login(UserServices.java:66) 

是從未執行過我的登錄模塊。我錯過了什麼?

更新: 將登錄模塊.jar移動到它工作的Web應用程序中。也許我的Wild is有一些問題。這裏是我的模塊結構:

%wildfly_home%/modules/system/layers/base/login/mongodb/main/module.xml    
%wildfly_home%/modules/system/layers/base/login/mongodb/main/mongo-java-driver-3.0.3.jar 
%wildfly_home%/modules/system/layers/base/login/mongodb/main/MongoLoginModule.jar 

,這是module.xml

<module xmlns="urn:jboss:module:1.1" name="login.mongodb"> 
    <resources> 
     <resource-root path="MongoLoginModule.jar"/> 
     <resource-root path="mongo-java-driver-3.0.3.jar"/> 
    </resources> 
    <dependencies> 
     <module name="org.apache.log4j"/> 
     <module name="javax.api"/> 
     <module name="org.slf4j"/> 
    </dependencies> 
</module> 

我必須弄清楚爲什麼登錄模塊不可達的Wildfly模塊。

+1

您是如何打包並安裝包含您的自定義LoginModule的服務器模塊(「login.mongodb」)的?您可以嘗試在第一步避免使用服務器模塊並將自定義登錄模塊包含在您的應用程序WAR中(在此情況下,將standalone.xml中的模塊屬性從安全域配置中移除)。 – kwart

+0

我在閱讀你的評論之前做了你建議的測試。我將登錄模塊jar包含在Web應用程序中,並從standalone.xml登錄模塊節點中刪除了模塊屬性。它的工作原理,現在我必須弄清楚爲什麼登錄模塊無法作爲Wildfly模塊訪問。我更新了我的問題。 – Francesco

回答

1

我的應用程序無法找到該模塊,因爲我忘了補充Dependency到它的MANIFEST或宣佈login.mongodb作爲Wildfly中的全局模塊。感謝@kwart對你的建議和你的回答,你指點我正確的方向。

1

這可能是WildFly的一個問題(或功能)。我已經將它報告爲WildFly JIRA WFLY-5569

您仍然可以使用正常工作的標準servlet認證。

添加WEB-INF/jboss-web.xml文件到您的部署:

<jboss-web> 
    <security-domain>MongoLoginRealm</security-domain> 
</jboss-web> 

調整代碼中使用HttpServletRequest.login(String, String)方法

@Context 
private HttpServletRequest req; 

@POST 
@Path("/login") 
@PermitAll 
@Consumes(MediaType.APPLICATION_JSON) 
public Response login(User userCredentials) { 
    try { 
     req.login(userCredentials.getUserName(), 
      userCredentials.getPassword()); 
     Subject subject = org.jboss.security.SecurityContextAssociation.getSubject(); 
     Optional<Group> rolesGroup = subject.getPrincipals(Group.class).stream().filter(p -> "Roles".equals(p.getName())) 
       .findFirst(); 
     if (rolesGroup.isPresent()) { 
      List<String> roleNames = Collections.list(rolesGroup.get().members()).stream().map(p -> p.getName()) 
        .collect(Collectors.toList()); 
      // ... 
     } else { 
      // ... 
     } 
    } catch (ServletException e) { 
     log.error("login fails.", e); 
     return Response.status(Status.FORBIDDEN).entity("Not logged") 
      .type(MediaType.APPLICATION_JSON_TYPE).build(); 
    } 
}