28
1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 – 12/4/13 Présentation du cours Ce cours montre comment sécuriser une application Java EE : réserver l’accès de pages Web (ou de méthodes d’EJB) à certains utilisateurs Toute la sécurité n’est pas standardisée dans Java EE ; pour les parties non standardisées, des exemples de configuration sont donnés pour le serveur d’application GlassFish R. Grin Sécurité Java EE page 2 R. Grin Sécurité Java EE page 3 Plan (1/2) Généralités sur la sécurité Présentation de la sécurité dans Java EE et fichiers de configuration Rôles et identité des utilisateurs – Authentification Protection des pages Web Protéger les méthodes des EJB Code Java pour la sécurité Configuration de GlassFish R. Grin Sécurité Java EE page 4 Plan (2/2) Un exemple Logs dans GlassFish Gérer les mots de passe R. Grin Sécurité Java EE page 5 Généralités sur la sécurité Réserver des parties d’une application à certains utilisateurs implique de gérer n l’authentification des utilisateurs n la vérification des autorisations R. Grin Sécurité Java EE page 6

Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

1

Sécurité dans Java EE

Université de Nice - Sophia AntipolisRichard Grin

Version 0.12 – 12/4/13

Présentation du cours

Ce cours montre comment sécuriser une application Java EE : réserver l’accès de pages Web (ou de méthodes d’EJB) à certains utilisateursToute la sécurité n’est pas standardisée dans Java EE ; pour les parties non standardisées, des exemples de configuration sont donnés pour le serveur d’application GlassFish

R. Grin Sécurité Java EE page 2

R. Grin Sécurité Java EE page 3

Plan (1/2)

Généralités sur la sécuritéPrésentation de la sécurité dans Java EE et fichiers de configurationRôles et identité des utilisateurs – AuthentificationProtection des pages WebProtéger les méthodes des EJBCode Java pour la sécuritéConfiguration de GlassFish

R. Grin Sécurité Java EE page 4

Plan (2/2)

Un exempleLogs dans GlassFishGérer les mots de passe

R. Grin Sécurité Java EE page 5

Généralités sur la sécurité

Réserver des parties d’une application à certains utilisateurs implique de gérern l’authentification des utilisateursn la vérification des autorisations

R. Grin Sécurité Java EE page 6

Page 2: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

2

Authentification

Obtenir l’identité des utilisateurs et vérifier qu’un utilisateur est bien celui qu’il prétend êtreLe plus souvent, il s’agit de demander le nom et le mot de passe de l’utilisateur

R. Grin Sécurité Java EE page 7

Autorisation

Lorsqu’un utilisateur est entré dans l’application,vérifier qu’il a bien le droit n d’accéder aux ressources (pages Web, base

de données,…) n d’accomplir des actions sur ces ressources

(par exemple les consulter, les modifier, les supprimer)

n de lancer des opérations

R. Grin Sécurité Java EE page 8

Transport des informations

Protéger les informations qui transitent sur le réseau contre des personnes non autorisés :n empêcher la lecture des données

confidentiellesn repérer qu’une information transmise a été

modifiée par une tierce personne avant d’arriver à destination

R. Grin Sécurité Java EE page 9

Ce support n’abordera que l’authentification par mot de passe et les autorisationsIl n’abordera pas, par exemple, l’étude des certificats et de la signature des documentsLes transparents suivants donnent la terminologie habituelle liée à la sécurité

R. Grin Sécurité Java EE page 10

UtilisateurL’utilisateur d’une application est identifié par des « pièces d’identité », credentials en anglais, qui prouvent son identitéLe plus souvent la saisie d’un nom de login et d’un mot de passe prouve l’identité d’un utilisateurL’utilisateur peut correspondre à une personne ou à une (partie d’une) application informatique

R. Grin Sécurité Java EE page 11 Richard Grin EJB page 12

Principal

Une fois qu’il est authentifié, l’utilisateur devient un principal (terme anglais qui signifie mandant, commettant) au nom duquel il effectuera des opérations dans l’applicationUn Principal peut être un utilisateur, un groupe d’utilisateurs, ou autre, qui a été défini dans l’environnement opérationnel d’exécution

Page 3: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

3

R. Grin Sécurité Java EE page 13

RôleLa politique de sécurité des serveurs d’application repose sur la notion de rôleExemples de rôle : administrateur, organisateur, participant, chef de serviceUn principal / utilisateur peut avoir un ou plusieurs rôles dans une applicationUn rôle donne des droits aux utilisateurs qui ont ce rôleLa notion de rôle augmente la portabilité de l’application puisqu’on ne fait aucune prévision sur l’existence d’utilisateurs particuliers

Rôles d’un utilisateur

C’est celui qui déploie l’application qui associe ces rôlesLa manière dont un rôle est associé à un utilisateur n’est pas standard et dépend du serveur d’applicationsTomcat et GlassFish définissent des groupes d’utilisateurs et il est possible de les configurer pour qu’un groupe corresponde à un rôle (voir section « Configuration GlassFish » plus loin dans ce support)

R. Grin Sécurité Java EE page 14

Groupes d’utilisateurs

Les utilisateurs sont souvent regroupés en groupes qui ont les mêmes types d’autorisation, ce qui facilite l’attribution de rôles aux utilisateurs (on peut donner en bloc un rôle à tous les membres d’un groupe)Par exemple, le groupe des utilisateurs enregistrés, le groupe des visiteurs non enregistrés, le groupe des administrateurs

R. Grin Sécurité Java EE page 15

Realm – domaine de sécuritéPour authentifier les utilisateurs, les serveurs d’application doivent conserver des informations sur ces utilisateursUn domaine de sécurité (realm), identifié par son nom, définit comment ces informations sont conservées, et comment on les utilise pour l’authentification (voir balise <login-config> de web.xml) ; la définition d’un realm n’est pas standardiséeExemples : domaine défini par un fichier des mots de passe, par des tables relationnelles, par un registre LDAP, par des certificats informatiques

R. Grin Sécurité Java EE page 16

Intervenants dans le processus de développement

Le développeur écrit l’application et indique les rôles nécessaires pour les ressources protégéesL’administrateur du serveur d’application gère les utilisateurs et les groupes d’utilisateursCelui qui déploie l’application dans le serveur d’application indique la correspondance entre les utilisateurs et groupe d’utilisateurs et les rôles définis par l’application (le plus souvent en utilisant les fichiers de déploiement)

R. Grin Sécurité Java EE page 17 R. Grin Sécurité Java EE page 18

Présentation de la sécurité dans Java EE

Page 4: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

4

Richard Grin EJB page 19

Principe général

Écrire du code pour la sécurité est très complexe et il est préférable de s’appuyer le plus possible sur les facilités offertes par les serveurs d’application

Déclaration ou programmation

Java EE permet d’implémenter une politique de sécurité de façon déclarative ou par programmation JavaLe plus simple est d’utiliser les déclarations (annotations Java ou fichiers de déploiement XML) pour indiquer comment les ressources sont protégéesSi la façon déclarative ne suffit pas, il est possible de programmer les cas les plus complexes en Java

R. Grin Sécurité Java EE page 20

DéclarationLes annotations permettent d’écrire les informations sur la politique de sécurité directement dans le code Java des EJB ou des servletsIl n’est pas toujours possible d’utiliser une annotation ; en ce cas les informations de sécurité sont décrites dans des balises des fichiers de déploiementToutes les annotations ont leur pendant sous forme de balise XML ; en cas de contradiction, une information dans un fichier de déploiement l’emporte sur une annotation

R. Grin Sécurité Java EE page 21

Fichiers de déploiement

Fichiers standards qui ne dépendent pas du serveur d’application : web.xml (module Web), ejb-jar.xml (module EJB), application.xml(module application qui peut regrouper plusieurs modules dans un fichier EAR)Chaque serveur d’application peut aussi avoir ses propres fichiers de déploiement pour les informations non standardisées ; pour GlassFish, glassfish-web.xml, glassfish-ejb-jar.xml, glassfish-application-web.xml

R. Grin Sécurité Java EE page 22

Types de déclarations

Java EE permet de déclarer n les rôles utilisés par l’applicationn la façon d’authentifier les utilisateursn les pages Web protégées et les rôles qui y ont

accèsn les classes ou méthodes Java protégées et les

rôles qui y ont accès

R. Grin Sécurité Java EE page 23

Nous allons tout d’abord étudier comment définir les rôles puis comment authentifier un utilisateurNous verrons enfin comment protéger des pages Web, puis comment restreindre l’accès à des méthodes JavaL’attribution de rôles à un utilisateur n’est pas standardisée ; elle sera étudiée pour le cas de GlassFish

R. Grin Sécurité Java EE page 24

Page 5: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

5

R. Grin Sécurité Java EE page 25

Définition des rôles

Déclaration des rôles

Un rôle doit être déclaré avant d’être utiliséOn peut le faire avec une annotation ou dans un fichier de déploiement XML

R. Grin Sécurité Java EE page 26

Annotation pour déclarer des rôles

L’annotation @DeclareRoles peut être mise sur les EJB ou les servletsLa casse (majuscules – minuscules) est significative dans les noms de rôleExemple :@Stateless@DeclareRoles("admin", "membre", "visiteur")public class MonBean { ... }

R. Grin Sécurité Java EE page 27

Balise pour déclarer des rôles

Plusieurs balises <security-role> peuventêtre mises directement sous la balise racine(web-app, ejb-jar ou application)Exemple :<security-role><description>Administrateur</description><role-name>admin</role-name>

</security-role><security-role><role-name>membre</role-name>

</security-role>

R. Grin Sécurité Java EE page 28

Référence d’un rôle

Le développeur utilise des noms de rôle dans son code lorsqu’il écrit un module Java EES’il réutilise son module dans plusieurs applications, un nom de rôle peut avoir un autre nom dans les autres modulesAvec la balise <security-role-ref> il est possible de définir un alias pour un nom de rôle, pour faire correspondre le rôle du module avec un rôle de l’environnement d’exécution

R. Grin Sécurité Java EE page 29 Richard Grin Sécurité Java EE page 30

Exemple d’alias pour un rôle

Le responsable du déploiement indiquera le rôle de l’environnement de déploiement (Controleur) associé au rôle indiqué par le développeur d’EJB (Admin) :<security-role-ref><description> . . . </description><role-name>Admin</role-name><role-link>Controleur</role-link>

</security-role-ref>

Si l’utilisateur a le rôle Controleur, isUserInRole("Admin") retourne true

Page 6: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

6

R. Grin Sécurité Java EE page 31

Authentification

Type d’authentification

Si l’utilisateur veut accéder à une page Web protégée et qu’il n’est pas déjà enregistré, le container Web cherche à l’authentifierLe plus souvent l’utilisateur s’authentifie en tapant son login et son mot de passe pour l’application dans un formulaireUn certificat peut aussi être utilisé pour l’authentification (mode CLIENT-CERT), à la place du login/mot de passe

R. Grin Sécurité Java EE page 32

Déclaration du type d’authentification

Pas d’annotation, il faut configurer avec la balise <login-config> sous la balise racine du fichier web.xml

2 sous-balises :n <auth-method> définit le mode d’authentificationn <realm-name> indique le domaine de sécurité

dans lequel les informations pour l’authentification seront cherchées ; il peut y en avoir plusieurs dans une application

R. Grin Sécurité Java EE page 33

Exemple

<login-config><auth-method>BASIC</auth-method><realm-name>candidatures</realm-name>

</login-config>

R. Grin Sécurité Java EE page 34

Valeurs par défaut

Par défaut, le mode d’authentification est le mode BASIC : le login et le mot de passe sont demandés à l’utilisateur par un formulaire affiché par le navigateur (ils transitent en clair sur le réseau)La valeur par défaut pour <realm-name> dépend du serveur d’applicationCe type risque de poser des problèmes car le navigateur garde souvent des informations sur l’utilisateur qui vient de se connecter ; préférer le mode FORM

R. Grin Sécurité Java EE page 35

Autres modes d’authentification

Plusieurs autres modes d’authentification, en plus du mode par défaut BASIC : n FORM : utilisation d’un formulaire écrit par le

développeur dans une page Web pour obtenir le login et le mot de passe

n DIGEST : utilisation d’un hachage pour le transport du mot de passe (MD5 par exemple)

n CLIENT-CERT : utilisation d’un certificat

R. Grin Sécurité Java EE page 36

Page 7: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

7

Exemple

<login-config><auth-method>FORM</auth-method><realm-name>candidatures</realm-name><form-login-config><form-login-page>/faces/login.xhtml</form-

login-page><form-error-page>/faces/noaut.xhtml</form-

error-page></form-login-config>

</login-config>

R. Grin Sécurité Java EE page 37

Mode FORM - pages

<form-login-config> ne sert que si <auth-method> a la valeur FORM, pour indiquer la page qui contient le formulaire de login et celle qui est affichée si le login et le mot de passe saisis ne sont pas bons

R. Grin Sécurité Java EE page 38

Mode FORM - formulaire de login

Si on choisit le mode FORM, le formulaire écrit par le développeur a des contraintes de nom pour n l’action exécutée lorsque le formulaire est

soumis (j_security_check)n les noms des champs qui contiennent le login

(j_username) et le mot de passe (j_password)

Ces contraintes vont permettre au container de vérifier le login et le mot de passe suivant le domaine de sécurité choisi par le développeur

R. Grin Sécurité Java EE page 39

Exemple de formulaire HTML

<form method="POST" action="j_security_check">Login : <input type="text" name="j_username"/>Mot de passe : <input type="password" name="j_password"/><input type="submit" value="Login"/>

</form>

R. Grin Sécurité Java EE page 40

Exemple de formulaire JSF<form method="post" action="j_security_check">

<h:panelGrid columns="2"><h:outputLabel for="j_username"

value="Login" /><h:input id="j_username" /><h:outputLabel for="j_password"

value="Mot de passe" /><h:inputSecret id="j_password"/><h:commandButton id="submit"

value="Login" /></h:panelGrid>

</form>R. Grin Sécurité Java EE page 41

Exemple de page d’erreur

<html><head><title>Echec de l'authentification</title>

</head><body><p>Désolé, vous n'avez pas tapé des bons login et mot de passe. Essayez à nouveau. </p>

</body></html>

R. Grin Sécurité Java EE page 42

Page 8: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

8

La méthode que l’on vient de voir est la façon la plus simple de filtrer les accès à une applicationElle convient le plus souvent mais elle a des contraintes importantes (les action et propriétés pour enregistrer les login et mots de passe sont imposés)Depuis JSF 2.0, le développeur peut choisir une autre solution plus souple mais plus complexe à programmer

R. Grin Sécurité Java EE page 43

Méthode HttpServletRequest.login()

Depuis JSF 2.0, il est possible de récupérer le nom et le mot de passe comme on le souhaite et de passer les valeurs à la méthode login(String nom, String mdp) de la classe HttpServletRequest pour s’authentifier auprès du container (lance une ServletException si déjà connecté ou mauvais login/mot de passe).

R. Grin Sécurité Java EE page 44

Utilisation login – formulaire

<h:form>Login :<h:inputText value="#{login.login}"

required="true" /> <p/>Mot de passe :<h:inputSecret value="#{login.mdp}"

required="true" /> <p/><h:commandButton value="Connexion"

action="#{login.submit}"><f:ajax execute="@form" render="@form" />

</h:commandButton><h:messages globalOnly="true" />

</h:form>

R. Grin Sécurité Java EE page 45

Remarque sur le code

Le code du backing bean de la solution avec la méthode login est un peu complexe ; il tire parti du fait que le container utilise un forward pour faire afficher la page qui contient le formulaire de loginPour avoir l’URI de la page que voulait l’utilisateur, il faut utiliser l’attribut de la requête RequestDispatcher.FORWARD_REQUEST_URIMerci à BalusC (expert JSF) pour l’information

R. Grin Sécurité Java EE page 46

Utilisation login – backing bean

@ManagedBean@ViewScopedpublic class Login {private String login, mdp;private String uri;

@PostConstructpublic void init() {

uri = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestMap() .get(RequestDispatcher.FORWARD_REQUEST_URI);

}

R. Grin Sécurité Java EE page 47

Utilisation login – backing bean

public void submit() throws IOException {FacesContext context =

FacesContext.getCurrentInstance();HttpServletRequest request = (HttpServletRequest)

context.getExternalContext().getRequest();try {

request.login(login, mdp);context.redirect(uri);

} catch (ServletException e) {facesContext.addMessage(...);

}}

R. Grin Sécurité Java EE page 48

Page 9: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

9

Déconnexion

L’authentification de l’utilisateur est valable pour toute la session de travail HTTPIl est possible de faire sortir l’utilisateur de la session de travail avec la méthode logout() de la classe HttpServletRequestCette méthode peut être appelée, par exemple, dans la méthode action d’un bouton sur lequel l’utilisateur peut cliquer pour se déconnecterUn exemple d’utilisation est donné dans la section « Code Java pour la sécurité » de ce support

R. Grin Sécurité Java EE page 49

SSL

Les login et mot de passe seront passés en clair sur le réseauIl est possible d’utiliser SSL pour les protéger ; la façon de le faire dépend du serveur d’application et ne sera pas étudié dans ce supportVoir aussi la section « Protection des pages Web »

R. Grin Sécurité Java EE page 50

Gestion des utilisateurs

La gestion des utilisateurs (ajout d’un nouvel utilisateur, modification,…) et la conservation des informations sur les utilisateurs dépend du serveur d’applicationLa section « Sécurité avec GlassFish » donne un exemple d’utilisation du serveur GlassFish

R. Grin Sécurité Java EE page 51

Les sections suivantes montrent comment réserver l’accès des pages Web et des méthodes Java des EJB ou des servlets aux utilisateurs qui ont un certain rôleEnsuite, il est montré comment configurer GlassFish pour les parties qui dépendent du serveur d’application

R. Grin Sécurité Java EE page 52

Protection des pages Web

R. Grin Sécurité Java EE page 53 R. Grin Sécurité Java EE page 54

Utilité

Le plus souvent des pages Web (définies par des URL) ne doivent être accessibles que par certains utilisateurs ou dans certaines circonstancesCette section explique comment restreindre l’accès d’une partie des pages d’une application à certains utilisateurs

Page 10: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

10

Erreurs HTTP pour la sécurité

Lorsqu’un utilisateur veut accéder à une page protégée,n erreur HTTP 401, Unauthorized, si l’utilisateur

ne fournit pas les credentials (le plus souvent le bon mot de passe)

n erreur HTTP 403, Forbidden, si l’utilisateur a fournit les bons credentials mais n’a pas l’autorisation d’accéder à la page

R. Grin Sécurité Java EE page 55

Schéma de protection

Le plus simple est d’utiliser le système de sécurité offert par les containers de page Web des serveurs d’applicationIl est simple de grouper les pages à protéger dans un ou plusieurs répertoires et de filtrer l’accès à ces répertoiresPour les cas plus complexes de filtrage, il est possible de coder le filtrage directement dans le code Java de l’application

R. Grin Sécurité Java EE page 56

Déclaration des protections

La protection est déclarée dans le fichier web.xmlpar des contraintes de sécurité déclarées sur des ressources (les pages Web désignées par des modèles d’URL)Il est aussi possible de déclarer des contraintes de sécurité dans un servlet (si l’application en a un) avec l’annotation @HttpConstraint contenue dans une annotation @ServletSecurity

R. Grin Sécurité Java EE page 57

Notions utilisées

L’application peut définir des contraintes de sécurité (<security-constraint>)Elles restreignent l’accès à des ressources (page Web définies par leur URL) aux seuls utilisateurs qui ont un certain rôle (plusieurs rôles peuvent être indiqués)Lorsqu’un utilisateur veut accéder à une ressource protégée, il doit être authentifié et il peut accéder à la ressource s’il a les rôles requis par la ressource

R. Grin Sécurité Java EE page 58

Contraintes de sécurité

Les sous balises de <security-constraint> :n <web-resource-collection> indique les

URLs des pages (<url-pattern>) et les méthodes HTTP protégées (<http-method>)

n <auth-constraint> indique les rôles qui permettent d’accéder aux pages

n <user-data-constraint> indique comment sont protégées les données échangées entre le client et le serveur (aucune protection par défaut)

R. Grin Sécurité Java EE page 59

Exemple<security-constraint><web-resource-collection><web-resource-name>r1</web-resource-name><url-pattern>/liste.xhtml</url-pattern>

</web-resource-collection><auth-constraint> <role-name>employe<role-name><role-name>drh<role-name>

</auth-constraint> </security-constraint>

R. Grin Sécurité Java EE page 60

Page 11: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

11

<url-pattern>

Les pages protégées sont désignées par la sous-balise <url-pattern> qui donne un chemin qui peut comporter le joker *3 Formats possibles pour un url-pattern :n commence par / et se termine par /* (toute page

située sous le répertoire qui précède « /* », à n’importe quelle profondeur

n commence avec *. et se termine par un caractère (par exemple *.jsf)

n commence par / et ne comporte pas de *R. Grin Sécurité Java EE page 61

Exemple - JSF<security-constraint><web-resource-collection><web-resource-name>p1</web-resource-name><url-pattern>/faces/candids/*</url-pattern><url-pattern>/candids/*</url-pattern>

</web-resource-collection><auth-constraint>

<role-name>admin</role-name><role-name>rsr</role-name>

</auth-constraint></security-constraint>

R. Grin Sécurité Java EE page 62

<http-method>

L’accès est protégé pour toutes les méthodes HTTP si cette balise est omise

R. Grin Sécurité Java EE page 63

Exemple<security-constraint><web-resource-collection><web-resource-name>r1</web-resource-name><url-pattern>/liste.xhtml</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method>

</web-resource-collection><auth-constraint> <role-name>employe<role-name>

</auth-constraint> </security-constraint>

R. Grin Sécurité Java EE page 64

Lien vers une page protégée

C’est l’URL de la page que l’on veut afficher qui est comparé aux patterns des pages protégéesSi une page contient un lien vers une page protégée, il faut écrire ce lien avec les composants <h:outputLink>, <h:button> ou <h:link>,ou ajouter une redirection à un un lien avec un composant <h:commandButton> ou <h:commandLink>

R. Grin Sécurité Java EE page 65

Attention, pas de forward interne !

Un forward interne au serveur (méthode forwardde RequestDispatcher) ne déclenche pas une vérification des contraintes de sécurité puisque l’URL n’est pas modifiéCe qui signifie qu’un <h:commandButton> ou un <h:commandLink> (sans redirection) vers une page protégée donnera accès à la page, même si l’utilisateur n’a pas l’autorisation d’accès à cette page

R. Grin Sécurité Java EE page 66

Page 12: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

12

<auth-constraint>

L’autorisation sera accordée si l’utilisateur a un des rôles indiqués« * » indique que tous les rôles sont acceptésS’il y a une balise <auth-constraint> mais aucune sous-balise <role-name>, les pages ne pourront être accédée par aucun utilisateur

R. Grin Sécurité Java EE page 67

<user-data-constraint>

La balise <user-data-constraint> peut être ajoutée dans une balise <security-constraint>pour indiquer que la connexion avec les pages protégées utilisera le protocole HTTPSElle contient une balise <transport-garantee>dont la valeur peut être égale à NONE (valeur par défaut), CONFIDENTIAL ou INTEGRAL

R. Grin Sécurité Java EE page 68

Valeurs pour <transport-garantee>

CONFIDENTIAL : les données transmises ne peuvent être vues par des tiersINTEGRAL : les données transmises ne peuvent être modifiées par des tiersNONE : pas de protection particulièreEn pratique, les 2 modes CONFIDENTIAL et INTEGRAL sont traités de la même façon par les serveurs d’application (utilisation de HTTPS)

R. Grin Sécurité Java EE page 69

Exemple<security-constraint><web-resource-collection><web-resource-name>r1</web-resource-name><url-pattern>/faces/restr/*</url-pattern>

</web-resource-collection><auth-constraint> <role-name>employe<role-name>

</auth-constraint> <user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint></security-constraint>

R. Grin Sécurité Java EE page 70

Avec les servlets

Dans le cas des applications qui n’utilisent pas les EJB, on peut utiliser les fichiers de configuration mais il est aussi possible de configurer la sécurité avec l’annotation @ServletSecurity

Les transparents suivant donne des exemples

R. Grin Sécurité Java EE page 71

Exemple 1@WebServlet("/monurl")@ServletSecurity(@HttpConstraint(rolesAllowed={"r1", "r2"}))

public class MaServlet extends HttpServlet

R. Grin Sécurité Java EE page 72

L’URL /monurl sera réservée aux utilisateurs qui ont le rôle « r1 » ou le rôle « r2 »

Page 13: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

13

Exemple 2@WebServlet("/monurl")@ServletSecurity(value=@HttpConstraint(

transportGuarantee=ServletSecurity.TransportGuarantee.CONFIDENTIAL),

httpMethodConstraints={ @HttpMethodConstraint(

value="TRACE", transportGuarantee=

ServletSecurity.TransportGuarantee.NONE, rolesAllowed={"r1"}) })

public class MaServlet extends HttpServlet

R. Grin Sécurité Java EE page 73

Protéger les méthodes des EJB

R. Grin Sécurité Java EE page 74

Par déclaration

Avec une annotationAvec les fichiers de déploiement XMLLes fichiers XML l’emportent sur les annotations

R. Grin Sécurité Java EE page 75

Annotation @RolesAllowed

Annote une méthode ou une classe (concerne alors toutes les méthodes de la classe) protégéeEn paramètre, un seul rôle ou plusieurs rôles de type String entourés d’accolades (les utilisateurs ayant un des rôles peuvent utiliser la méthode ou la classe) :@RolesAllowed("role1")@RolesAllowed({ "role1", "role2" })

R. Grin Sécurité Java EE page 76

Annotation @PermitAll

Si la classe est protégée, cette annotation permet d’exclure une méthode de la protection : tous les utilisateurs seront autorisés à utiliser la méthode annotée par @PermitAll

R. Grin Sécurité Java EE page 77 R. Grin Sécurité Java EE page 78

Exemple de déclarations (1/2)<ejb-jar><assembly-descriptor><security-role><description>Employés chargés des clients</description><role-name>Caissier</role-name>

</security-role><security-role><description>Contrôleur</description><role-name>Controleur</role-name>

</security-role>

Page 14: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

14

R. Grin Sécurité Java EE page 79

Exemple de déclarations (2/2)<method-permission><role-name>Controleur</role-name><method><ejb-name>Compte</ejb-name><method-name>getBalance</method-name>

</method><method><ejb-name>Compte</ejb-name><method-name>setBalance</method-name>

</method></method-permission>

</assembly-descriptor></ejb-jar>

R. Grin Sécurité Java EE page 80

Méthodes non protégées

Certaines méthodes sont autorisées à tous (unchecked):<method-permission>

<role-name>unchecked</role-name><method><ejb-name>Compte</ejb-name><method-name>getNames</method-name>

</method>

R. Grin Sécurité Java EE page 81

Méthodes non accessibles

Des méthodes peuvent ne pas être accessibles pour un déploiement :<exclude-list><description>Méthode m1 de Ejb1 interdite</description><method><ejb-name>Ejb1</ejb-name> <method-name>m1</method-name>

</method></exclude-list>

Annotation @RunAs

Peut annoter une méthode d’un EJB (si la classe EJB est annotée, toutes les méthodes de la classe sont concernées)Le paramètre est le nom du rôle que l’utilisateur prendra pendant qu’il exécutera la méthodeExemple :@RunAs("admin")

R. Grin Sécurité Java EE page 82

R. Grin Sécurité Java EE page 83

Balise run-as

Dans un fichier de configuration :<session><ejb-name>. . . </ejb-name>. . .<security-identity><run-as><role-name>admin</role-name>

</run-as></security-identity>. . .

</session>

R. Grin Sécurité Java EE page 84

use-caller-identity

Pour être certain qu’on utilisera le principal et pas un rôle donné par une méthode EJB « run-as », on peut indiquer use-caller-identity pour un EJB ; en ce cas, les rôles transmis seront les rôles liés à la vraie identité de l’utilisateur (sinon ça serait le rôle donné par « run-as ») :<security-identity><use-caller-identity/>

</security-identity>

Page 15: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

15

Code Java pour la sécurité

R. Grin Sécurité Java EE page 85 R. Grin Sécurité Java EE page 86

Sécurité par programmation

Dans certains cas la déclaration des autorisations dans les fichiers de déploiement ou par des annotations n’est pas assez soupleDans ces cas, on peut écrire du code Java qui prend en compte les cas particuliersL’exemple suivant montre comment distinguer des utilisateurs qui ont le même rôle dans une application JSF

R. Grin Sécurité Java EE page 87

Cas d’utilisation

Dans une application qui gère des formations, les utilisateurs doivent ouvrir un compteCe compte leur donne le rôle « etudiant » qui leur permet de s’inscrire à des cours et de participer à des forumsCependant ces étudiants ne peuvent voir et modifier que leurs données personnelles, ce qui impose une programmation en Java

Les transparents suivants étudient le cas d’une application JSF, avec le code qu’un backing beanpeut contenirOn verra ensuite comment obtenir les mêmes informations dans une méthode d’un EJB session

R. Grin Sécurité Java EE page 88

R. Grin Sécurité Java EE page 89

Dans un backing bean JSF

Il est possible de récupérer le nom de l’utilisateur avec le code suivant :FacesContext context = FacesContext.getCurrentInstance();

HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();

String login = request.getRemoteUser();

Classe ExternalContext

Cette classe du paquetage javax.faces.context permet d’obtenir des informations sur l’environnement d’exécution ; elle contient en particulier des méthodes utiles pour la sécuritéUne instance peut être obtenue par FacesContext.getCurrentInstance().getExternalContext()

R. Grin Sécurité Java EE page 90

Page 16: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

16

R. Grin Sécurité Java EE page 91

Méthodes de ExternalContext

boolean isUserInRole(String nomRole)retourne true si celui qui appelle la méthode remplit bien le rôle passé en paramètrejava.security.PrincipalgetUserPrincipal() permet d’avoir le principalde celui qui appelle la méthode, ce qui permet de distinguer des utilisateurs qui ont le même rôleObject getRequest() récupère la requête en cours (caster en javax.servlet.http.HttpServletRequest)

Exemple avec JSF

...String login = request.getRemoteUser();if (<condition sur login>) {FacesContext.getCurrentInstance() .getExternalContext() .redirect(autrePage);

}...

R. Grin Sécurité Java EE page 92

Sortir d’une application JSF

Après ce code (qu’on peut mettre, par exemple, dans l’action d’un bouton), l’utilisateur devra à nouveau s’authentifier pour les fonctionnalités qui nécessite une authentification :try {((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).logout();

} catch (ServletException ex) {…

}R. Grin Sécurité Java EE page 93

Dans un EJB

Pour filtrer les accès aux méthodes des EJB dans le cas où la granularité de protection offerte par les rôles ne suffit pas, il est possible d’utiliser les méthodes de l’interface javax.ejb.EJBContextCette interface est implémentée par la classe javax.ejb.SessionContextOn peut obtenir une instance de SessionContexten l’injectant dans un EJB session :@Resourceprivate SessionContext contexte;

R. Grin Sécurité Java EE page 94

Méthodes de EJBContext

EJBContext contient des méthodes liées à l’authentification des utilisateurs :n Principal getCallerPrincipal()n boolean isCallerInRole(String role)

Elles jouent le même rôle que les méthodes de l’interface ExternalContext (avec User à la place de Caller)

R. Grin Sécurité Java EE page 95

Exemple

// Méthode interdite à certains utilisateursString login = contexte.getCallerPrincipal().getName();

if (condition sur login) {// l’utilisateur n’a pas le droit// de faire exécuter ce traitementthrow new TrucException(...);

}// Traitement métier effectué par la méthode...

R. Grin Sécurité Java EE page 96

Page 17: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

17

Configuration de GlassFish

R. Grin Sécurité Java EE page 97

Mode de configuration

GlassFish peut être configurén du côté du serveur : avec la console

d’administration ou avec la commande asadmin

n en ajoutant dans l’application des fichiers de configuration de déploiement particuliers à GlassFish ; ces fichiers seront pris en compte par GlassFish quand l’application sera déployée sur le serveur

R. Grin Sécurité Java EE page 98

Console d’administration de GlassFish

Elle s’affiche dans un navigateur en tapant l’adresse du serveur, suffixé avec « :4848 » (port d’écoute)

R. Grin Sécurité Java EE page 99

Commande asadmin (1/2)

Cette commande est située dans le répertoire bin du répertoire d’installation de GlassFish (répertoire affiché dans la console d’administration de GlassFish)La commande asadmin prend en paramètre des commandes qui permettent de configurer le serveur (« asadmin --help » affiche une aide ; « asadmincommande --help » affiche une aide sur une commande)

R. Grin Sécurité Java EE page 100

Commande asadmin (2/2)

On peut travailler avec asadmin en mode interactif en tapant « asadmin multimode » ; un prompt « asadmin> » apparaît et on peut taper plusieurs commandes ; taper « exit » pour sortirOn peut aussi lancer un script qui contient des commandes par « asadmin multimode --file script.txt »

R. Grin Sécurité Java EE page 101

Si GlassFish ne veut plus démarrerIl peut s’agir d’un problème de configurationA essayer :n Aller dans le répertoire qui contient domain.xml ; il

contient aussi un fichier domain.xml.bak qui est la l’avant-dernière version de domain.xml

n Conserver les 2 fichiers et ensuite renommer domain.xml.bak en domain.xml et essayer de redémarrer GlassFish

n Si GlassFish redémarre, essayer de comprendre le problème en faisant un « diff » des 2 fichiers (peut venir, par exemple, de caractères particuliers, accents ou autres, dans les chemins des fichiers désignés)

R. Grin Sécurité Java EE page 102

Page 18: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

18

Fichiers de déploiement GlassFish

Ils ont les mêmes noms que les fichiers de déploiement standard, préfixés par glassfish- :glassfish-application.xml, glassfish-ejb-jar.xml, glassfish-web.xml

R. Grin Sécurité Java EE page 103

Affecter les rôles avec GlassFish

La manière dont un rôle est associé à un utilisateur dépend du serveur d’applicationGlassFish (et Tomcat) définit des groupes d’utilisateursOn peut affecter un ou plusieurs rôles à un groupe ou à un utilisateurPour simplifier, il est aussi possible de configurer GlassFish pour que les groupes ou les utilisateurs correspondent aux rôles de même noms

R. Grin Sécurité Java EE page 104

Indiquer une correspondance avec un rôlePour indiquer la correspondance entre les groupes (ou les utilisateurs) et les rôles, 2 possibilités :n utiliser un fichier de déploiement de l’application

particulier à GlassFish pour donner les correspondances entre groupes et rôles

n utiliser la console d’administration de GlassFish ou la commande asadmin pour indiquer que les rôles correspondent aux groupes d’utilisateurs ou utilisateurs de même nom de GlassFish (s’applique à toutes les applications qui n’utilisent pas la 1ère possibilité)

R. Grin Sécurité Java EE page 105

Avec un fichier de déploiement

Pour indiquer une correspondance entre un groupe (group-name) ou un utilisateur (principal-name) et un rôle (role-name) il suffit d’ajouter une balise <security-role-mapping> sous la balise racine du fichier

R. Grin Sécurité Java EE page 106

Exemple

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE glassfish-web-app PUBLIC "…"

"http://glassfish.org/…"><glassfish-web-app>...<security-role-mapping>

<role-name>admin</role-name><principal-name>root</principal-name><principal-name>bob</principal-name><group-name>administrateur</group-name>

</security-role-mapping>...

R. Grin Sécurité Java EE page 107

Dans glassfish-web.xml

Par défaut, principal = rôle

Pour simplifier, il est possible d’indiquer à GlassFish que les groupes ou utilisateurs correspondent aux rôles de même nom (sauf si une correspondance explicite d’un rôle et d’un principal est donnée)Les applications déjà déployées ne sont pas affectées par une modification de l’activation du mapping par défaut des principaux avec des rôlesPendant le développement il ne faut donc pas oublier de redéployer l’application après un changement de statut de cette activation

R. Grin Sécurité Java EE page 108

Page 19: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

19

Par défaut, principal = rôle

Avec la commande asadmin :asadmin set server-config.security-service.activate-default-principal-to-role-mapping=trueasadmin set server-config.security-service.mapped-principal-class=CustomPrincipalImplClassAvec le menu de la console d’administration :Configuration > server-config > Securité > Cocherla case Default Principal To Role Mapping (en français : Mise en correspondance par défaut des principaux avec des rôles)

R. Grin Sécurité Java EE page 109

Gestion des utilisateurs

La manière de conserver les informations sur l’identité de l’utilisateur, telles que les logins et mots de passe, n’est pas standardGlassFish et Tomcat utilisent pour cela la notion de domaine (realm en anglais) qui correspond au domaine utilisée dans la balise <realm-name>de la balise <login-config>

R. Grin Sécurité Java EE page 110

Domaine de sécurité

Dans GlassFish il y a les types de realms suivants : n file (informations dans un simple fichier ;

domaine par défaut)n jdbc (dans des tables d’un SGBDR)n ldap (utilise un registre LDAP)n certificate (utilise des certificats)

Il est aussi possible de créer son propre type de realm (pas étudié dans ce cours)

R. Grin Sécurité Java EE page 111

Créer un domaine de sécurité

asadmin create-auth-realmpermet de créer un realmOn peut aussi passer par les menus de la console d’administration (voir exemple à suivre pour un domaine de type JDBC)

R. Grin Sécurité Java EE page 112

Les transparents suivants étudient le type de domaine JDBC qui est souvent utilisé car il permet d’ajouter simplement de nouveaux utilisateurs (des utilisateurs peuvent ainsi, par exemple, créer leur propre « espace membre » pour l’application)

R. Grin Sécurité Java EE page 113

Étapes pour créer un domaine JDBC

1. Créer les tables qui contiennent les informations sur les utilisateurs

2. Définir une source de données liée à la base de données qui contient ces tables

3. Créer le domaine JDBC

R. Grin Sécurité Java EE page 114

Page 20: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

20

Structure des tables

La table des utilisateurs doit avoir n une colonne qui contient le nom de loginn une colonne qui contient le mot de passe (en clair ou

crypté) ; de type chaîne de caractères dont la longueur dépend du codage du mot de passe

La table des groupes (en fait la table qui fait correspondre un groupe et un utilisateur) doit avoirn une colonne qui contient le nom d’un groupen une colonne qui contient un nom de login

Ces tables peuvent avoir d’autres colonnes

R. Grin Sécurité Java EE page 115

Exemple de création des tables

Table des utilisateurs (mot de passe crypté en SHA256 avec codage Hex ; il faut donc 64 caractères) :create table utilisateur (login varchar(20) primary key,mot_de_passe varchar(64))

Table des groupes :create table groupe (nom_groupe varchar(20),login varchar(20))

R. Grin Sécurité Java EE page 116

Exemple de données

Dans la table des groupes :toto, groupe1toto, groupe2admin, adminpour indiquer que toto appartient aux groupes groupe1 et groupe 2 et admin appartient au groupe admin

R. Grin JSF page 117

Vues au-dessus des tables

Si ces informations (login et groupe) sont dans des tables qui n’ont pas exactement le format voulu, il est possible d’utiliser des vues et non pas des tables dans la définition des domaines

R. Grin Sécurité Java EE page 118

Exemple de vue pour les groupes

Table utilisateur (login, mot_de_passe, email)Table groupe(id_groupe, nom_groupe)Table groupe_utilisateur(id_groupe, login) ; le problème est que id_groupe est utilisé et pas nom-groupeVue v_groupe_utilisateur qui va servir comme « table » des groupes : create view v_groupe_utilisateur asselect login, nom_groupefrom groupe join groupe_utilisateur

on groupe.id_groupe = groupe_utilisateur.id_groupeR. Grin Sécurité Java EE page 119

Définition de la source de données

Il faut maintenant créer une source de données dont une référence sera rangée dans l’annuaire JNDI de GlassFish utilisable par l’applicationIl faut commencer par créer un pool de connexions JDBC puis créer la source de données en utilisant ce pool de connexions2 possibilités :n avec la console d’administration de GlassFishn avec la commande asadmin

R. Grin Sécurité Java EE page 120

Page 21: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

21

Pool de connexions

Il décrit l’accès à la base de données (machine serveur, nom de la base, port d’écoute,..)Avec les menus de la console d’administration : Ressources > JDBC > Pool de connexions JDBCAvec asadmin create-jdbc-connectionExemple asadmin :asadmin create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --propertyuser=dbuser:password=mdpdb:url="jdbc:oracle\:thin\:@localhost\:1521\:ORCL" monpool

R. Grin Sécurité Java EE page 121

Ressource JDBC

Il faut ensuite créer une ressource JDBC en utilisant le pool de connexions ; on lui donnera le nom JNDI jdbc/candidatures pour l’utiliser dans les transparents suivantsAvec les menus de la console d’administration : Ressources > JDBC > Resources JDBCAvec asadmin create-jdbc-resourceExemple :asadmin create-jdbc-resource --connectionpoolid monpooljdbc/masource

R. Grin Sécurité Java EE page 122

Création d’un realm JDBC (1/3)

Console d’administration de GlassFishConfigurations > server-config > Sécurité > DomainesCliquer NouveauNom : candidaturesNom de classe : celle qui se nomme JDBCRealmIl s’affiche des propriétés qu’il faut renseigner (éviter de taper des lettres accentuées ; problèmes possibles)

R. Grin JSF page 123

Création d’un realm JDBC (2/3)

Contexte de JAAS : jdbcRealmJNDI : jdbc/candidatures (nom de la source de données qui contient les tables)Table d’utilisateurs : PERSONNE (attention à respecter la casse des tables de la BD si MySQL)Colonne de nom d’utilisateur : LOGINColonne de mot de passe : MOT_DE_PASSETable de groupes : GROUPEColonne de nom de groupe : NOM_GROUPE

R. Grin JSF page 124

Création d’un realm JDBC (3/3)

Algorithme condensé : algorithme de hachage utilisé pour condenser le mot de passe ; SHA256 par défaut (MD5 dans les anciennes versions de GlassFish)Codage : indique comment le mot de passe condensé (suite d’octets) sera enregistré sous la forme d’une chaîne de caractères dans la base de données (Hex ou Base64) ; la chaîne de caractères sera de longueur 32 pour MD5 et de longueur 64 pour SHA256

R. Grin JSF page 125

Modification d’un domaine de sécurité

Il faut relancer GlassFish pour qu’il tienne compte des modifications (à vérifier…)

R. Grin Sécurité Java EE page 126

Page 22: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

22

En cas d’erreur

Attention, si le domaine de sécurité n’est pas défini, le message d’erreur de GlassFish ne l’indique pas ; pour tous les login / mot de passe, il dit seulement que le login a échoué

R. Grin Sécurité Java EE page 127

Commandes asadmin en batchIl est possible d’écrire un script (fichier texte) qui contient plusieurs commandes de asadmin et de lancer son exécution en « batch » parasadmin multimode --file script.txtLe transparent suivant contient un exemple de script avec 3 commandes pour créer un domaine de sécurité JDBC ; il faudra remplacer les 12 « variables » (dans 15 emplacements) par de valeurs car il n’y a pas de notion de variable avec les scripts asadmin ; ne pas passer à la ligne à l’intérieur de chaque commande asadmin

R. Grin Sécurité Java EE page 128

Exempleasadmin create-jdbc-connection-pool --datasourceclassnameorg.apache.derby.jdbc.ClientDataSource --restype javax.sql.DataSource--property PortNumber=${DATABASE_PORT}:Password=${DATABASE_PASSWORD}:User=${DATABASE_USER}:ServerName=localhost:DatabaseName=${DATABASE_NAME} ${CONNECTION_POOL_NAME}asadmin create-jdbc-resource --connectionpoolid${CONNECTION_POOL_NAME} ${JNDI_NAME}asadmin create-auth-realm --classnamecom.sun.enterprise.security.auth.realm.jdbc.JDBCRealm --property user-name-column=${USER_NAME}:password-column=${PASSWORD}:group-name-column=${GROUP_NAME}:jaas-context=jdbcRealm:datasource-jndi="${JNDI_NAME}":group-table=${GROUP_TABLE}:user-table=${USER_TABLE} ${REALM_NAME}R. Grin Sécurité Java EE page 129

Exemple qui utilise Java DB (Derby)asadmin create-jdbc-connection-pool --datasourceclassnameorg.apache.derby.jdbc.ClientDataSource --restype javax.sql.DataSource--propertyPortNumber=1527:Password=toto:User=toto:ServerName=localhost:DatabaseName=base1 derbyPoolasadmin create-jdbc-resource --connectionpoolid derbyPool jdbc/dbasadmin create-auth-realm --classnamecom.sun.enterprise.security.auth.realm.jdbc.JDBCRealm --property user-name-column=LOGIN:password-column=MOT_DE_PASSE:group-name-column=NOM_GROUPE:jaas-context=jdbcRealm:datasource-jndi="jdbc/db":group-table=GROUPE:user-table=PERSONNE realm1

R. Grin Sécurité Java EE page 130

Modifier le fichier web.xml

Il faut maintenant indiquer que ce realm devra être utilisé lors de l’identification des utilisateursUn exemple d’utilisation du realm« candidatures » est donné dans le transparent suivant

R. Grin JSF page 131

Extrait de web.xml

<login-config><auth-method>FORM</auth-method><realm-name>candidatures</realm-name><form-login-config><form-login-page>/faces/login.xhtml</form-login-page><form-error-page>/faces/noauth.xhtml</form-error-page>

</form-login-config></login-config>

R. Grin JSF page 132

Page 23: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

23

Un exemple avec template

R. Grin Sécurité Java EE page 133

Cet exemple va utiliser une authentification avec le domaine JDBC et un formulaire écrit par le développeur (type FORM)

R. Grin Sécurité Java EE page 134

Modèle de page

Si on veut que toutes les pages de l’application indiquent le nom de l’utilisateur et permettent de se déconnecter de l’application, il faut prévoir un template qui contient ces fonctionnalitésLes transparents suivant donnent un exemple d’un tel templateLes détails sont donnés dans la section « Code Java pour la sécurité » de ce cours et dans le cours JSF sur les templates

R. Grin Sécurité Java EE page 135

Exemple de template (1/3)

<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-...N" ...><html xmlns="http://www.w3.org/1999/xhtml"

xmlns:ui="http://java.sun.com/jsf/facelets"xmlns:h="http://java.sun.com/jsf/html"xmlns:f="http://java.sun.com/jsf/core">

<f:event type="preRenderView" listener="#{bean.infosUser}" />

<ui:insert name="metadata"/>

R. Grin Sécurité Java EE page 136

Pour retrouver les informations sur l’utilisateur

Exemple de template (2/3)

<h:head><meta http-equiv="Content-Type"

content="text/html; charset=UTF-8" /><h:outputStylesheet library="css"

name="cssLayout.css" /><title>#{bundle.titreGeneral}</title>

</h:head>

R. Grin Sécurité Java EE page 137

Pour internationaliser ; dans faces-config.xml :<resource-bundle><base-name>/Bundle</base-name><var>bundle</var>

</resource-bundle>

Exemple de template (3/3)

<h:body><div id="top" class="top">

<ui:insert name="top">#{bundle.titreGeneral} -<h:outputText value="#{bean.login.login}"

rendered="#{bean.login.login} != ''"/> -<h:outputText value="#{bean.login.nom}"

rendered="#{bean.login.nom} != ''"/></ui:insert>

</div>...

</body>

R. Grin Sécurité Java EE page 138

Page 24: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

24

Code bean session - getLogin

public Login getLogin() {// login contient la personne connectéeif (login == null) {

String nomUtilisateur =FacesContext.getCurrentInstance()

.getExternalContext().getRemoteUser();if (nomUtilisateur != null) {

login = loginFacade.find(nomUtilisateur);}

}return login;

}

R. Grin Sécurité Java EE page 139

Code bean session - infosUser

public void infosUser(ComponentSystemEvent event) {if (login != null) { // infos déjà obtenues

return;}String loginUtilisateur =

((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRemoteUser();

if (loginUtilisateur != null) {login = loginFacade.find(loginUtilisateur);

}}

R. Grin Sécurité Java EE page 140

Déconnexion

Il faut permettre à l’utilisateur de se déconnecterLe plus simple est d’ajouter un bouton pour cela qui appelle une méthode du backing bean qui appelle la méthode logout() de la classe HttpServletRequest

R. Grin Sécurité Java EE page 141

Code bean session - logout

public String logout() {login = null;try {

((HttpServletRequest) FacesContext.getCurrentInstance()

.getExternalContext().getRequest()).logout();} catch (ServletException ex) {

Logger.getLogger(Bean.class.getName()).log(Level.SEVERE, null, ex);

}return "/index";

}

R. Grin Sécurité Java EE page 142

Logs dans GlassFish -Mise au point

R. Grin Sécurité Java EE page 143

Écrire dans les fichiers de logs

Dans du code Java, System.out.printlnenvoie dans les logs de GlassFish au niveau INFOSystem.err.println envoie dans les logs de GlassFish au niveau SEVEREIl est aussi possible d’écrire à d’autres niveau en utilisant explicitement l’API de logging du JDK

R. Grin Sécurité Java EE page 144

Page 25: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

25

Exemple

import java.util.logging.Logger; ...private Logger log = Logger.getLogger(MaClass.class.getName());

...log.warning("Mon message.");

R. Grin Sécurité Java EE page 145

Afficher les logs

Les derniers logs s’affichent avec la console d’administration de GlassFish : serveur, onglet « Général », bouton « Afficher les fichiers journaux »On peut aussi aller directement voir le contenu des fichiers

R. Grin Sécurité Java EE page 146

Où se trouvent les logs

Les fichiers de logs se trouvent par défaut dans le répertoire glassfish/domains/domain1/logs du répertoire d’installation de GlassFish (si on travaille avec le domaine domain1), par exemple dansC:\Program Files\glassfish-3.1.2\glassfish\domains\domain1\logsAttention, sous Windows, ces fichiers peuvent être ailleurs (voir les propriétés du serveur sous NetBeans, champ « Domains folder »)

R. Grin Sécurité Java EE page 147

Configuration des logs

Dans la console d’administration, Configurations, « Paramètres du journaliseur » (Logger Settings an anglais)

R. Grin Sécurité Java EE page 148

Pour la mise au point avec GlassFish

Configurer le niveau du logger de GlassFish javax.enterprise.system.core.security à FINEST avec la console d’administration de GlassFish (Configurations, server-config, Paramètres du logger/journaliseur en français, onglet Niveaux de journalisation)Des informations intéressantes pour résoudre des problèmes de sécurité sont alors affichées dans les logs de GlassFish

R. Grin Sécurité Java EE page 149

Gérer les mots de passe

R. Grin Sécurité Java EE page 150

Page 26: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

26

Cette section expose quelques généralités sur la gestion des login / mots de passe

R. Grin Sécurité Java EE page 151

Conserver les mots de passe

Pour authentifier les utilisateurs, 2 solutions :n s’appuyer sur un système d’authentification

externe, tel LDAPn gérer les mots de passe dans l’application

Nous allons étudier le 2ème cas

R. Grin Sécurité Java EE page 152

A ne pas faire !

Ne jamais conserver les mots de passe en clair dans l’applicationNe pas utiliser des algorithmes de cryptage ou de hashage faciles à déjouerPar exemple, ne pas utiliser MD5 (aller par exemple sur le site http://www.md5hacker.com/ qui permet de trouver rapidement un mot de passe qui correspond à une valeur MD5)

R. Grin Sécurité Java EE page 153

Saler !

Les mots de passe doivent donc être conservés cryptés dans l’applicationPour compliquer la recherche d’une série de mots de passe, il faut ajouter une valeur aléatoire, le sel, différente pour tous les utilisateurs, qui sera ajoutée au mot de passe de chaque utilisateurLe sel peut être conservé en clair avec le mot de passe crypté

R. Grin Sécurité Java EE page 154

Utilisation du sel

L’application récupère le mot de passe tapé par l’utilisateur, elle concatène le sel au mot de passe et elle crypte le tout en une valeur v1L’application vérifie que la valeur v0 qu’elle conserve (le mot de passe de l’utilisateur, concaténé au sel et crypté au moment de l’enregistrement du mot de passe) est bien égale à v1 ; si ça n’est pas le cas, c’est que le mot de passe tapé n’était pas le bon

R. Grin Sécurité Java EE page 155

Mots de passe avec GlassFishLes dernières versions de GlassFish utilisent par défaut le codage SHA-256 pour hasher les mots de passe (on peut choisir lorsqu’on définit un domaine de sécurité)GlassFish récupère le mot de passe par un getString alors que les algorithmes de hashagefournissent un tableau d’octets ; la façon de passer du tableau d’octets à une String doit être indiquée dans la définition du domaineEn standard GlassFish ne permet pas de saler les mots de passe

R. Grin Sécurité Java EE page 156

Page 27: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

27

Enregistrer un mot de passe

On peut l’enregistrer sous la forme de byte[] ou de StringBase64 est le plus souvent utilisé pour la transformation de byte[] en StringHex peut aussi être utilisé (écriture en hexadécimal de chaque octet et concaténation de tous les octets ; 2 chiffres par octet)Si on ne précise rien dans la définition du domaine, GlassFish va passer par un char[] en utilisant un codage (UTF-8)

R. Grin Sécurité Java EE page 157

Exemple de code

L’exemple suivant peut être utilisé tel quel dans une application qui voudrait gérer elle-même l’authentification en utilisant du selIl est extrait et adapté du code de Jerry Orr donné dans un article qui traite de la façon de conserver les mots de passe, trouvé à l’adresse http://jerryorr.blogspot.fr/2012_05_01_archive.html

R. Grin Sécurité Java EE page 158

Exemple de code (1/4)

import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.Arrays; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec;

public class PasswordEncryptionService {

R. Grin Sécurité Java EE page 159

D’après code de Jerry Orr ; http://jerryorr.blogspot.fr/2012_05_01_archive.html

Exemple de code (2/4)

public boolean authenticate(String attemptedPassword, byte[] encryptedPassword, byte[] salt)

throws NoSuchAlgorithmException, InvalidKeySpecException {

byte[] encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt);

return Arrays.equals(encryptedPassword, encryptedAttemptedPassword);

}

R. Grin Sécurité Java EE page 160

Exemple de code (3/4)public byte[] getEncryptedPassword(String password, byte[] sel)

throws NoSuchAlgorithmException, InvalidKeySpecException {

// Nom algorithme (PBKDF2 avec SHA-1)String algo = "PBKDF2WithHmacSHA1";int longueurCle = 160; // SHA-1 génère 160 bitsint iterations = 20000; // Au moins 1000KeySpec spec = new PBEKeySpec(

password.toCharArray(), sel, iterations, longueurCle);SecretKeyFactory f = SecretKeyFactory.getInstance(algo);return f.generateSecret(spec).getEncoded();}

R. Grin Sécurité Java EE page 161

Exemple de code (4/4)

// Utilisé la 1ère fois pour générer un sel.// On peut garder le même si le mot de passe changepublic byte[] generateSalt()

throws NoSuchAlgorithmException {SecureRandom random =

SecureRandom.getInstance("SHA1PRNG");// Genère un sel de 8 octets (64 bits)byte[] sel = new byte[8];random.nextBytes(sel);return sel;}

R. Grin Sécurité Java EE page 162

Page 28: Présentation du cours - Freerichard.grin.free.fr/emsi/rabat/supports/securiteJavaEE.pdf1 Sécurité dans Java EE Université de Nice - Sophia Antipolis Richard Grin Version 0.12 –

28

Attention à l’injection de code SQL

Si l’application écrit son propre code SQL pour vérifier un couple login/mot de passe enregistré dans une base de données, attention à l’injection de code SQL (voir cours sur la sécurité en Java http://deptinfo.unice.fr/~grin/messupports/java/Securite6.pdf)Pas de crainte avec la façon standard de vérifier un mot de passe dans une base utilisée par GlassFish

R. Grin Sécurité Java EE page 163