2014-07-23 1 views
1

J'ai créé un LoginModule personnalisé pour authentifier les utilisateurs présents dans les collections de mongoDB. Dans mon cas, j'ai besoin d'un rôle par page ... J'ai déjà utilisé l'authentification JAAS avec JSF, mais dans ce cas, cela ne fonctionne pas comme prévu ... Il renvoie toujours l'erreur 403 (Interdit). Le mappage des URL est apparemment OK.Java/WildFly/MongoDB/JAAS - L'authentification renvoie toujours 403 - Interdit

C'est ma hiérarchie pages:

  • app < -root
    • pages
      • mes pages protégées (un rôle par page)
    • login.html
    • login_error .html
    • index.html

Suivez mes configurations:

jboss-web.xml

<jboss-web> 
    <security-domain>nfceSecurityDomain</security-domain> 
    <disable-audit>true</disable-audit> 
</jboss-web> 

web.xml

<session-config> 
    <session-timeout>30</session-timeout> 
</session-config> 

<login-config> 
    <auth-method>FORM</auth-method> 
    <form-login-config> 
      <form-login-page>/app/login.html</form-login-page> 
      <form-error-page>/app/login_error.html</form-error-page> 
    </form-login-config> 
</login-config> 

<security-role> 
    <role-name>VISUALIZAR_NOTAS</role-name> 
</security-role> 
<security-role> 
    <role-name>GESTAO_CERTIFICADO</role-name> 
</security-role> 
<security-role> 
    <role-name>GESTAO_EMPRESA</role-name> 
</security-role> 
<security-role> 
    <role-name>DOWNLOAD_XML</role-name> 
</security-role> 
<security-role> 
    <role-name>INUTILIZACAO</role-name> 
</security-role> 

<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>index</web-resource-name> 
     <url-pattern>/app/index.html</url-pattern> 
     <http-method>POST</http-method> 
     <http-method>GET</http-method> 
     <http-method>PUT</http-method> 
     <http-method>DELETE</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
      <role-name>VISUALIZAR_NOTAS</role-name> 
    </auth-constraint> 
</security-constraint> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>orderList</web-resource-name> 
     <url-pattern>/app/pages/orderlist.html</url-pattern> 
     <http-method>POST</http-method> 
     <http-method>GET</http-method> 
     <http-method>PUT</http-method> 
     <http-method>DELETE</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>VISUALIZAR_NOTAS</role-name> 
    </auth-constraint> 
</security-constraint> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>certificateConfigurations</web-resource-name> 
     <url-pattern>/app/pages/certifiedlist.html</url-pattern> 
     <http-method>POST</http-method> 
     <http-method>GET</http-method> 
     <http-method>PUT</http-method> 
     <http-method>DELETE</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>GESTAO_CERTIFICADO</role-name> 
    </auth-constraint> 
</security-constraint> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>enterpriseConfigurations</web-resource-name> 
     <url-pattern>/app/pages/enterpriselist.html</url-pattern> 
     <http-method>POST</http-method> 
     <http-method>GET</http-method> 
     <http-method>PUT</http-method> 
     <http-method>DELETE</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>GESTAO_EMPRESA</role-name> 
    </auth-constraint> 
</security-constraint> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>xmlDownload</web-resource-name> 
     <url-pattern>/app/pages/orderdownload.html</url-pattern> 
     <http-method>POST</http-method> 
     <http-method>GET</http-method> 
     <http-method>PUT</http-method> 
     <http-method>DELETE</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>DOWNLOAD_XML</role-name> 
    </auth-constraint> 
</security-constraint> 
<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>invalidate</web-resource-name> 
     <url-pattern>/app/pages/orderInvalidate.html</url-pattern> 
     <http-method>POST</http-method> 
     <http-method>GET</http-method> 
     <http-method>PUT</http-method> 
     <http-method>DELETE</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>INUTILIZACAO</role-name> 
    </auth-constraint> 
</security-constraint> 

standalone.xml

<subsystem xmlns="urn:jboss:domain:security:1.2"> 
      <security-domains> 
       <security-domain name="nfceSecurityDomain" cache-type="default"> 
        <authentication> 
         <login-module code="br.com.ciss.nfce.security.JAASLoginModule" flag="required"/> 
        </authentication> 
       </security-domain> 
      </security-domains> 
     </subsystem> 

Et voici ma mise en œuvre de LoginModule, pour obtenir l'utilisateur et les rôles de MongoDB:

public class JAASLoginModule implements LoginModule { 

    private static final Logger LOG = Logger.getLogger(JAASLoginModule.class); 

    private Subject subject; 
    private CallbackHandler callbackHandler; 
    private Map sharedState; 
    private Map options; 

    private boolean succeeded = false; 
    private boolean commitSucceeded = false; 

    private String username = null; 
    private String _idUser = ""; 
    private char[] password = null; 

    private Principal userPrincipal = null; 
    private Principal passwordPrincipal = null; 

    private ConnectionMongoUtil connectionMongoUtil; 

    public JAASLoginModule() { 
     super(); 
    } 

    @Override 
    public void initialize(Subject subject, CallbackHandler callbackHandler, 
      Map<String, ?> sharedState, Map<String, ?> options) { 
     this.subject = subject; 
     this.callbackHandler = callbackHandler; 
     this.sharedState = sharedState; 
     this.options = options; 
    } 

    @Override 
    public boolean login() throws LoginException { 

     if (callbackHandler == null) { 
      throw new LoginException("Error: no CallbackHandler available " 
        + "to garner authentication information from the user"); 
     } 
     Callback[] callbacks = new Callback[2]; 
     callbacks[0] = new NameCallback("username"); 
     callbacks[1] = new PasswordCallback("password: ", false); 

     try { 
      callbackHandler.handle(callbacks); 
      username = ((NameCallback) callbacks[0]).getName(); 
      password = ((PasswordCallback) callbacks[1]).getPassword(); 

      if (username == null || password == null) { 
       LOG.error("Callback handler does not return login data properly"); 
       throw new LoginException(
         "Callback handler does not return login data properly"); 
      } 

      if (isValidUser()) { // validate user. 
       succeeded = true; 
       return true; 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (UnsupportedCallbackException e) { 
      e.printStackTrace(); 
     } 

     return false; 
    } 

    @Override 
    public boolean commit() throws LoginException { 
     if (succeeded == false) { 
      return false; 
     } else { 
      userPrincipal = new JAASUserPrincipal(username); 
      if (!subject.getPrincipals().contains(userPrincipal)) { 
       subject.getPrincipals().add(userPrincipal); 
       LOG.debug("User principal added:" + userPrincipal); 
      } 
      passwordPrincipal = new JAASPasswordPrincipal(new String(password)); 
      if (!subject.getPrincipals().contains(passwordPrincipal)) { 
       subject.getPrincipals().add(passwordPrincipal); 
       LOG.debug("Password principal added: " + passwordPrincipal); 
      } 

      List<String> roles = getRoles(); 
      for (String role : roles) { 
       Principal rolePrincipal = new JAASRolePrincipal(role); 
       if (!subject.getPrincipals().contains(rolePrincipal)) { 
        subject.getPrincipals().add(rolePrincipal); 
        LOG.debug("Role principal added: " + rolePrincipal); 
       } 
      } 

      commitSucceeded = true; 
      LOG.info("Login subject were successfully populated with principals and roles"); 
      return true; 
     } 
    } 

    @Override 
    public boolean abort() throws LoginException { 
     if (succeeded == false) { 
      return false; 
     } else if (succeeded == true && commitSucceeded == false) { 
      succeeded = false; 
      username = null; 
      if (password != null) { 
       password = null; 
      } 
      userPrincipal = null; 
     } else { 
      logout(); 
     } 
     return true; 
    } 

    @Override 
    public boolean logout() throws LoginException { 
     subject.getPrincipals().remove(userPrincipal); 
     succeeded = false; 
     succeeded = commitSucceeded; 
     username = null; 
     if (password != null) { 
      for (int i = 0; i < password.length; i++) { 
       password[i] = ' '; 
       password = null; 
      } 
     } 
     userPrincipal = null; 
     return true; 
    } 

    private boolean isValidUser() throws LoginException { 

     try { 
      BasicDBObject search = new BasicDBObject(); 
      search.put("email", username); 
      connectionMongoUtil = new ConnectionMongoUtil(); 
      DBObject user = connectionMongoUtil.getCollection("User").findOne(search); 

      if (user == null){ 
       LOG.debug("USUÁRIO NÃO LOCALIZADO!"); 
       return false; 
      }else{ 
       if (new String(password).equals(user.get("password"))){ 
        _idUser = user.get("_id").toString(); 
        return true; 
       }else{ 
        LOG.debug("SENHA INVÁLIDA PARA O USUÁRIO " + username); 
       } 
      } 

      return false; 
     } catch (Exception e) { 
      LOG.error("Error when loading user " + username + " from the database \n", e); 
     } 

     return false; 
    } 

    /** 
    * Returns list of roles assigned to authenticated user. 
    * 
    * @return 
    */ 
    private List<String> getRoles() { 
     BasicDBObject search = new BasicDBObject(); 
     search.put("_idUser", _idUser); 
     DBObject userModules = connectionMongoUtil.getCollection("UserModules").findOne(search); 
     String jsonArrayModules = userModules.get("_idModules").toString(); 

     String[] modules = null; 
     try { 
      modules = new ObjectMapper().readValue(jsonArrayModules, String[].class); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     List<String> modulesList = new ArrayList<String>(); 
     for (String _idModule : modules) { 
      DBObject module = connectionMongoUtil.getCollection("Module").findOne(new BasicDBObject("_id", new ObjectId(_idModule))); 
      if (module != null){ 
       modulesList.add(module.get("name").toString()); 
      } 
     } 

     return modulesList; 
    } 
} 

J'ai ajouté la propriété suivante dans standalone.xml, pour voir les journaux générés par JAAS, et don « t ont tout journal d'erreurs ...

<logger category="org.jboss.security"> 
    <level name="ALL"/> 
</logger> 

dans mes collections de MongoDB, j'ai ajouté tous les rôles à mon utilisateur, et quand j'essaie de me connecter, je peux vous connecter, mais toutes les pages sont verrouillées , renvoyant l'erreur 403

Quelqu'un peut-il m'aider? Peut-être que c'est juste un petit détail causant l'erreur 403 ...

Merci de votre attention!

+0

Avez-vous essayé d'enregistrer la requête MongoDB utilisée et la valeur de retour? Si vous ne savez pas où ajouter les informations de débogage dans JAAS, vous pouvez essayer d'utiliser MongoDB [base de données de profil] (http://docs.mongodb.org/manual/tutorial/manage-the-database-profiler/) à un niveau de 2 (toutes les requêtes, au lieu de seulement des requêtes lentes). – Stennie

+0

Salut, merci pour votre réponse ... Je pense que le problème ne concerne pas les requêtes mongoDB, parce que je mets l'utilisateur et les rôles fixés dans JAASLoginModule, et la même erreur se produit. Je pense que l'erreur est dans une configuration JBoss ... – siega

+0

J'ai changé ce projet pour faire quelques tests et je l'ai partagé sur mon google drive ... Dans le google drive, il y a le projet (eclipse), le standalone Fichier .xml pour wildfly et les journaux générés lorsque j'ai essayé d'accéder aux pages ... Dans le projet, il y a deux implémentations de LoginModule, mais je n'utilise que JAASLoginModule. Si quelqu'un peut me aider, je serai très reconnaissant ... https://drive.google.com/folderview?id=0B_GgtF8zczPWbnV2cmVxZDlvQ3c&usp=sharing – siega

Répondre

0

La seule façon de résoudre cette situation est de changer JAAS par Spring Security :)

0

Je sais qu'il est un vieux fil, mais sans un bon Solution.

J'ai eu le même problème ...

Certains contexte: J'ai eu une application web java « en bonne santé » à l'aide JAA (mise en œuvre javax.security.auth.spi.LoginModule directement) sur le bon fonctionnement Tomcat7. Puis une exigence du client est venue dans la scène: "Il doit fonctionner sur JBoss 7.1.1" WTF? Même la version mineure et le patch!?!

Hands On: J'ai donc fait toute la configuration, avait quelques inconvénients avec le code Java 8 et JAX-RS, mais cela est une autre histoire, à la fin de mon application a été déployée avec succès dans JBoss 7.1.1.

Problème: Je pouvais voir dans la console de connexion était Successfull, mais toutes les demandes étaient de retour HTTP 403.

Lors du débogage tous les directeurs d'école (CallerPrincipal et UserRoles) étaient OK.

Aussi, j'ai une seule BaseServlet abstraite pour l'orchestration et que toutes les demandes doivent traverser, mais HTTP 403 avant l'atteindre produites à l '...

Solution: J'ai remarqué que tous les documents JBoss En ce qui concerne JAAS, je conseille aux développeurs d'étendre leur LoginModules personnalisé, donc j'ai commencé à creuser.

Le fichier org.jboss.security.auth.spi.AbstractServerLoginModule utilise ce qu'il appelle le "modèle standard JBossSX d'utilisation des identités et des rôles".

Je ne suis pas allé aussi loin pour expliquer le modèle, mais j'ai réappris le 'JBossWebRealm' qui enveloppe le processus d'authentification dans le côté du conteneur attend une implémentation java.security.acl.Group avec le nom "Roles" contenant Tous les principaux (CallerPrincipal et UserRoles) en tant que membres (L'appartenance de JAASRealm).

Cet objet est utilisé pour le contrôle de sécurité.

Fin de l'histoire, je l'ai ajouté cette méthode pour ma mise en œuvre de LoginModule:

public boolean commit() throws LoginException { 

    // some validation code here 

    Set<Principal> principals = subject.getPrincipals(); 

    // ensure principals contains (CallerPrincipal and UserRoles) 

    createRolesGroup(principals); 

    return true; 
} 

private void createRolesGroup(Set<Principal> principals) { 

    // Thee java.security.acl.Group implementation 
    SecurityGroup rolesGroup = new SecurityGroup("Roles"); 

    Iterator<Principal> iter = principals.iterator(); 

    while(iter.hasNext()) { 
     Object principal = iter.next(); 
     if(!(principal instanceof Group)){ 
     rolesGroup.addMember((Principal)principal); 
    } 

    principals.add(rolesGroup); 
} 

et fonctionne comme un charme.

Espérons que ça aide.