Wildfly和JAAS登录模块

我正在玩Wildfly-9.0.1.FinalJAAS但我没那么有趣..我实现了我的自定义登录模块:

 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 sharedState, Map 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 results = mongoDb.getCollection().find(new Document("username", userName)); return results.iterator().next(); } public void getRoles() { // FindIterable results = mongoDb.getCollection().find(new Document("username", userName)); // results.iterator().next().get } 

它并不完美,但它现在是应该的。 这个纯JAAS登录模块是我的Wildfly中的一个模块。 我这样配置安全域:

        

我实现了一些RESTful 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 roles = new ArrayList(); 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.xml auth-methodBASICrealm-nameMongoLoginRealm ,与jboss-web.xml和实例化LoginContext 。 当我调用login方法时,我遇到了这个exception:

 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应用程序中。 也许我的Wildfly出了点问题。 这是我的模块结构:

 %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

            

我必须弄清楚为什么登录模块不能作为Wildfly模块访问。

这可能是WildFly的一个问题(或特征)。 我已将它报告为WildFly JIRA WFLY-5569 。

您仍然可以使用可正常工作的标准servlet身份validation。

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

  MongoLoginRealm  

调整代码以使用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 rolesGroup = subject.getPrincipals(Group.class).stream().filter(p -> "Roles".equals(p.getName())) .findFirst(); if (rolesGroup.isPresent()) { List 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(); } } 

我的应用程序找不到该模块,因为我忘了将Dependency添加到它的MANIFEST或将login.mongodb声明为login.mongodb中的全局模块。 感谢@kwart的建议和答案,你指出了正确的方向。