Bonjour,

J'ai créé une application web vouée à être hébergée sur un serveur GlassFish 4.1.1.
Mon objectif est de m'authentifier auprès d'un seveur Active Directory.
La version non sécurisée se connecte sans soucis sur le port 389.
J'ai fait de multiples essais pour établir une connexion sécurisée via ldaps:\\mondomaine.xx:636\
J'obtient tout le temps une erreur PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
J'ai importé les certificats de mon serveur AD dans le répertoire : C:\Program Files\Java\jdk1.8.0_77\jre\lib\security\jssecacerts à l'aide de la commande keytool.
J'ai testé sur 2 machines différentes, j'ai toujours le même souci.

Si quelqu'un à une idée

Page de Login
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Gestionnaire de parc informatique</title>
        <link  rel="stylesheet" type="text/css" href="Ressources/template.css"/>
        <link rel="stylesheet" type="text/css" href="Ressources/index.css"/>
        <title> Login - Gestionnaire de parc informatique </title>
    </h:head>
    <h:body>
        <h:form id="loginForm">
            <p:panelGrid styleClass="personnalGrid">
                <p:row styleClass="personnalRow">
                    <p:column colspan="2" styleClass="personnalHeaderBar">
                        <p:outputLabel value="Connexion"/>
                    </p:column>
                </p:row>
                <p:row styleClass="personnalRow">
                    <p:column styleClass="personnalCell">
                        <p:outputLabel value="Login" for="loginInput"/>
                    </p:column>
                    <p:column styleClass="personnalCell" style="text-align: right;">
                        <p:inputText id="loginInput" value="#{loginCtrl.userInput}" required="true" requiredMessage="Saisissez votre login">
                        </p:inputText>
                    </p:column>
                </p:row>
                <p:row styleClass="personnalRow">
                    <p:column styleClass="personnalCell">
                        <p:outputLabel value="Mot de passe" for="passwordInput"/> 
                    </p:column>
                    <p:column styleClass="personnalCell" style="text-align: right;">
                        <p:password id="passwordInput" value="#{loginCtrl.passwordInput}" required="true" requiredMessage="Saisissez votre mot de passe"/>
                    </p:column>
                </p:row>
                <p:row styleClass="personnalRow">
                    <p:column colspan="2" styleClass="personnalCell">
                        <p:commandButton icon="fa fa-check" value="Se connecter" style="color:mediumblue;" styleClass="personnalButton" 
                                         update="loginForm" action="#{loginCtrl.doLogin()}"/>
                    </p:column>
                </p:row>
            </p:panelGrid>
            <p:messages id="loginMsg" closable="false" styleClass="personnalMessages"/>
        </h:form>
    </h:body>
</html>
Login Ctrl
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package XXX.ui;
 
import XXX.entity.People;
import XXX.entity.Users;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
 
/**
 *
 * @author Olivier Timmermans
 */
@Named("loginCtrl")
@SessionScoped
public class LoginControler extends EntityControler implements Serializable {
 
    @Inject
    private ActiveDirectoryControler adCtrl;
    @Inject
    private MenuControler menuCtrl;
    @Inject
    private UserControler userCtrl;
    @Inject
    private PeopleControler peopleCtrl;
 
 
    private String userInput;
    private String passwordInput;
    private Boolean loggedIn;
    private Users loggedInUser;
 
 
 
    /******************/
    /* Intialisations */
    /******************/
 
    @PostConstruct
    public void init() {
        loggedIn = false;
        menuCtrl.setActiveVerticalIndex(0);
        loggedInUser = new Users();
    }
 
    /***********************/
    /* Gestion des actions */
    /***********************/
 
    /*  Autheur : Timmermans Olivier 
        Description : Méthode de connexion à l'application 
        Modifications : 25-05-2016 : Ajout de la création automatique de l'utilisateur
                        lorsque celui-ci n'existe pas encore dans la table users
        Entrée : userInput => Nom d'utilisateur
                 passwordInput => Mot de passe
        Sortie : Message d'erreur en cas d'échec
                 Redirection vers la page d'acceuil en cas de succès
    */
    public String doLogin() {
        if (!adCtrl.connect(userInput, passwordInput)) {
            String message = "Le nom d'utilisateur ou le mot de passe n'est pas correct";
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));
            FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
            return "index.xhtml?faces-redirect=true";
        }
        loggedIn = true;
        loggedInUser.setLogin(userInput);
        loggedInUser = userCtrl.getUserByLogin(loggedInUser);
        if(loggedInUser == null)
        {
            peopleCtrl.doImportSingleUser(userInput);
            userCtrl.doImportSinglePeople(userInput, peopleCtrl.getCurrentPeople());
            loggedInUser = userCtrl.getCurrentUser();
        }
 
        menuCtrl.generateMenu();
        return "accueil.xhtml?faces-redirect=true";
    }
 
    /*  Autheur : Timmermans Olivier
        Description : Méthode de déconnexion de l'application
        Entrée : Aucune
        Sortie : Redirection vers la page de login
    */
    public String doLogout() {
        menuCtrl.init();
        loggedInUser = new Users();
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        return "index.xhtml?faces-redirect=true";
    }
 
    /*********************/
    /* Getters & Setters */
    /*********************/
 
    public String getUserInput() {
        return userInput;
    }
 
    public void setUserInput(String userInput) {
        this.userInput = userInput;
    }
 
    public String getPasswordInput() {
        return passwordInput;
    }
 
    public void setPasswordInput(String passwordInput) {
        this.passwordInput = passwordInput;
    }
 
    public Boolean isLoggedIn() {
        return loggedIn;
    }
 
    public void setLoggedIn(Boolean loggedIn) {
        this.loggedIn = loggedIn;
    }
 
    public Users getLoggedInUser() {
        return loggedInUser;
    }
 
    public void setLoggedInUser(Users loggedInUser) {
        this.loggedInUser = loggedInUser;
    }
 
}
ADControler

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
 
package XXX.ui;
 
import XXX.entity.*;
import java.io.File;
 
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.ini4j.Ini;
import org.ini4j.Profile.Section;
import org.primefaces.context.RequestContext;
 
/**
 *
 * @author Olivier Timmermans
 */
@Named("adCtrl")
@SessionScoped
public class ActiveDirectoryControler implements Serializable {
 
    /* Liste des attribus recherché pour les groupes et les utilisateurs */
    private final String[] searchedAttributes = {"GivenName", "sn", "SamAccountName", "mail", "DistinguishedName"};
    private final String[] groupAttributes = {"name"};
 
    /* Assignation des constantes */
    public static final int LDAPURL = 0;
    public static final int DOMAIN = 1;
    public static final int USERSCONTAINER = 2;
    public static final int GROUPSCONTAINER = 3;
 
    /* Variables du fichier INI */
    private FileReader fread;
    private Ini appSettings;
 
    /* Variables de connexion à l'Active Directory */
    private Hashtable<String, String> environment;
    private DirContext authContext;
    private List<String> adSettings;
 
    /* Groupes de sécurité */
    private List<String> accessGroupList;
 
    /* Variables d'application */
    private Attributes attributes;
    private AdUser tempAdUser;
    private List<AdUser> adUsers;
    private AdUser currentAdUser;
    private AdUser loggedInUser;
 
 
 
    /*******************/
    /* Initialisations */
    /*******************/
 
    /*  Autheur : Timmermans Olivier
        Description : Initialisation du controleur & chargements des paramètres
                      de connexion à l'AD
        Entrée : Aucune
        Sortie : Aucune
    */
    @PostConstruct
    public void init() {
        try {
            File classPath = new File(ActiveDirectoryControler.class.getProtectionDomain().getCodeSource().getLocation().toURI());
            String path = classPath.getAbsolutePath();
            path = path.replace("ActiveDirectoryControler.class", "ad.ini");
            fread = new FileReader(path);
            appSettings = new Ini();
            appSettings.load(fread);
            this.loadSettings();
 
            environment = new Hashtable<String, String>();
            environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            environment.put(Context.PROVIDER_URL,"ldaps://mondomaine.xx:636/");
            environment.put(Context.SECURITY_AUTHENTICATION, "simple");
            environment.put(Context.SECURITY_PROTOCOL, "ssl");
            System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files\\Java\\jdk1.8.0_77\\jre\\lib\\security\\jssecacerts");
            System.setProperty("javax.net.ssl.trustStorePassword", "monmotdepasse");
 
 
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ActiveDirectoryControler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException | URISyntaxException ex) {
            Logger.getLogger(ActiveDirectoryControler.class.getName()).log(Level.SEVERE, null, ex);
        }
        tempAdUser = new AdUser();
        currentAdUser = new AdUser();
        adUsers = new ArrayList<>();
    }
 
    /*  Autheur : Timmermans Olivier
        Description : Méthode de chargement des paramètres contenus dans le
                      fichier ini.
        Entrée : Aucune
        Sortie : Aucune
    */
 
    public void loadSettings() {
 
        // Chargement des informations de base de l'AD
        adSettings = new ArrayList<>();
        Section connexion = appSettings.get("Connexion");
        for (String optionKey : connexion.keySet()) {
            adSettings.add(connexion.get(optionKey));
        }
 
        // Chargemement de la liste des groupes de sécurité qui concernent l'application
        accessGroupList = new ArrayList<>();
        Section accessGroups = appSettings.get("AccessGroups");
        for (String optionKey : accessGroups.keySet()) {
            accessGroupList.add(accessGroups.get(optionKey));
        }
    }
 
    /*  Autheur : Timmermans Olivier
        Description : vérification des droits d'accès en fonction de la fonctionnalité
        Entrée : String contenant le nom de la fonctionnalité
        Sortie : Vrai => Accès
                 Faux => Pas d'accès
    */
 
    public Boolean hasPermission(String value) {
        return loggedInUser.getGroups().contains(appSettings.get("AccessGroups").get(value));
    }
 
    /*  Autheur : Timmermans Olivier
        Description : Méthode de connexion à l'AD
        Entrée : String login & String password
        Sortie : Vrai => Connexion OK
                 Faux => Echec de la connexion
    */
    public Boolean connect(String currentUser, String currentPassword) {
        try {
            environment.put(Context.SECURITY_PRINCIPAL, currentUser + "@" + adSettings.get(DOMAIN));
            environment.put(Context.SECURITY_CREDENTIALS, currentPassword);
            authContext = new InitialDirContext(environment);
            loggedInUser = getAdUser(currentUser);
        } catch (Exception ex) {
            System.out.println(ex);
            return false;
        }
        return true;
    }
 
    /*  Autheur : Timmermans Olivier
        Description : Méthode de récupération des données utilisateur dans l'AD
        Entrée : String samAccountName
        Sortie : Objet AdUser
    */
 
    public AdUser getAdUser(String currentUser) {
        try {
            SearchControls searchCtrls = new SearchControls();
            searchCtrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            searchCtrls.setReturningAttributes(searchedAttributes);
            String filter = "(&((&(objectCategory=Person)(objectClass=User)))(samaccountname=" + currentUser + "))";
            NamingEnumeration values = authContext.search(adSettings.get(USERSCONTAINER), filter, searchCtrls);
            while (values.hasMore()) {
                SearchResult result = (SearchResult) values.next();
                attributes = result.getAttributes();
                tempAdUser.setFirstName(attributes.get("sn").toString());
                tempAdUser.setFirstName(tempAdUser.getFirstName().replace("sn: ", ""));
                tempAdUser.setLastName(attributes.get("GivenName").toString());
                tempAdUser.setLastName(tempAdUser.getLastName().replace("givenName: ", ""));
                tempAdUser.setEmail(attributes.get("mail").toString());
                tempAdUser.setEmail(tempAdUser.getEmail().replace("mail: ", ""));
                tempAdUser.setSamAccountName(attributes.get("SamAccountName").toString());
                tempAdUser.setSamAccountName(tempAdUser.getSamAccountName().replace("sAMAccountName: ", ""));
                tempAdUser.setDn(attributes.get("DistinguishedName").toString());
                tempAdUser.setDn(tempAdUser.getDn().replace("distinguishedName: ", ""));
                RequestContext.getCurrentInstance().update("headerForm");
            }
        } catch (NamingException ex) {
            Logger.getLogger(ActiveDirectoryControler.class
                    .getName()).log(Level.SEVERE, null, ex);
        }
        tempAdUser.setGroups(getAdGroups());
        return tempAdUser;
    }
 
    /*  Autheur : Timmermans Olivier
        Description : Méthode de récupération des groupes de l'utilisateur courant
        Entrée : Aucune
        Sortie : Liste String contenant le nom des groupes AD
    */
    public List<String> getAdGroups() {
        List<String> adGroups = new ArrayList<>();
        try {
            SearchControls searchCtrls = new SearchControls();
            searchCtrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            searchCtrls.setReturningAttributes(groupAttributes);
            String filter = "(&(&(objectCategory=group)(member:1.2.840.113556.1.4.1941:=" + tempAdUser.getDn() + "))(name=GF*))";
            NamingEnumeration groups = authContext.search(adSettings.get(GROUPSCONTAINER), filter, searchCtrls);
            while (groups.hasMore()) {
                SearchResult result = (SearchResult) groups.next();
                Attributes grpAttributes = result.getAttributes();
                String groupName = grpAttributes.get("name").toString();
                groupName = groupName.replace("name: ", "").replace(adSettings.get(GROUPSCONTAINER), "");
                adGroups.add(groupName);
            }
        } catch (NamingException ex) {
            Logger.getLogger(ActiveDirectoryControler.class.getName()).log(Level.SEVERE, null, ex);
 
        }
        return adGroups;
    }
 
    /*  Autheur : Timmermans Olivier
        Description : Méthode de récupération de la liste des utilisateurs AD
        Entrée : Aucune
        Sortie : Liste d'objet AdUser
    */
 
    public List<AdUser> getAdUsers() {
        if (!adUsers.isEmpty()) {
            adUsers.clear();
        }
        try {
            SearchControls searchCtrls = new SearchControls();
            searchCtrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            searchCtrls.setReturningAttributes(searchedAttributes);
            String filter = "(&(objectCategory=person)(objectClass=user))";
            NamingEnumeration values = authContext.search(adSettings.get(USERSCONTAINER), filter, searchCtrls);
            while (values.hasMore()) {
                tempAdUser = new AdUser();
                SearchResult result = (SearchResult) values.next();
                attributes = result.getAttributes();
                tempAdUser.setFirstName(attributes.get("sn").toString());
                tempAdUser.setFirstName(tempAdUser.getFirstName().replace("sn: ", ""));
                tempAdUser.setLastName(attributes.get("GivenName").toString());
                tempAdUser.setLastName(tempAdUser.getLastName().replace("givenName: ", ""));
                tempAdUser.setEmail(attributes.get("mail").toString());
                tempAdUser.setEmail(tempAdUser.getEmail().replace("mail: ", ""));
                tempAdUser.setSamAccountName(attributes.get("SamAccountName").toString());
                tempAdUser.setSamAccountName(tempAdUser.getSamAccountName().replace("sAMAccountName: ", ""));
                tempAdUser.setDn(attributes.get("DistinguishedName").toString());
                tempAdUser.setDn(tempAdUser.getDn().replace("distinguishedName: ", ""));
                adUsers.add(tempAdUser);
            }
        } catch (NamingException ex) {
            Logger.getLogger(ActiveDirectoryControler.class.getName()).log(Level.SEVERE, null, ex);
        }
        return adUsers;
    }
 
    /*********************/
    /* Getters & Setters */
    /*********************/
 
    public void setAdUsers(List<AdUser> adUsers) {
        this.adUsers = adUsers;
    }
 
    public AdUser getCurrentAdUser() {
        return currentAdUser;
    }
 
    public void setCurrentAdUser(AdUser currentAdUser) {
        this.currentAdUser = currentAdUser;
    }
 
    public AdUser getLoggedInUser() {
        return loggedInUser;
    }
 
    public void setLoggedInUser(AdUser loggedInUser) {
        this.loggedInUser = loggedInUser;
    }
}