• Aucun résultat trouvé

Présentation du cours. Sécurité dans Java EE. Plan (1/2) Plan (2/2) Généralités sur la sécurité

N/A
N/A
Protected

Academic year: 2022

Partager "Présentation du cours. Sécurité dans Java EE. Plan (1/2) Plan (2/2) Généralités sur la sécurité"

Copied!
31
0
0

Texte intégral

(1)

Sécurité dans Java EE

Université de Nice - Sophia Antipolis Richard Grin

Version 0.17 – 17/9/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

‰Déclaration des rôles

‰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 avec template

‰Logs dans GlassFish – mise au point

‰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

nl’authentification des utilisateurs

nla vérification des autorisations

R. Grin Sécurité Java EE page 6

(2)

Authentification

‰Obtenir l’identité des utilisateurs et vérifier qu’un utilisateur est bien celui qu’il prétend être

‰Le 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

nd’accéder aux ressources (pages Web, base de données,…)

nd’accomplir des actions sur ces ressources (par exemple les consulter, les modifier, les supprimer)

nde 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 :

nempêcher la lecture des données confidentielles

nrepé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 autorisations

‰Il n’abordera pas, par exemple, l’étude des certificats et de la signature des documents

‰Les transparents suivants donnent la terminologie habituelle liée à la sécurité

R. Grin Sécurité Java EE page 10

Utilisateur

‰L’utilisateur d’une application est identifié par des

« pièces d’identité », credentialsen 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 utilisateur

‰L’utilisateur peut correspondre à une personne ou à une (partie d’une) application informatique

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’application

‰Un principalpeut être un utilisateur, un groupe d’utilisateurs, ou autre, qui a été défini dans l’environnement opérationnel d’exécution

(3)

R. Grin Sécurité Java EE page 13

Rôle

‰La politique de sécurité des serveurs d’application repose sur la notion de rôle

‰Exemples de rôle : administrateur, organisateur, participant, chef de service

‰Un principal / utilisateur peut avoir un ou plusieurs rôles dans une application

‰Un rôle donne des droits aux utilisateurs qui ont ce rôle

‰La 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ôles

‰La manière dont un rôle est associé à un utilisateur n’est pas standard et dépend du serveur d’application

‰Tomcat et GlassFish définissent des groupes d’utilisateurset 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 utilisateurs

‰Un 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 realmn’est pas standardisée

‰Exemples : 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ées

‰L’administrateurdu serveur d’application gère les utilisateurs et les groupes d’utilisateurs

‰Celui qui déploiel’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

(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 Java

‰Le plus simple est d’utiliser les déclarations (annotations Java ou fichiers de déploiement XML) pour indiquer comment les ressources sont protégées

‰Si 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éclaration

‰Les annotations permettent d’écrire les

informations sur la politique de sécurité directement dans le code Java des EJB ou des servlets

‰Il 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éploiement

‰Toutes 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

nles rôles utilisés par l’application

nla façon d’authentifier les utilisateurs

nles pages Web protégées et les rôles qui y ont accès

nles classes ou méthodes Java protégées et les rôles qui y ont accès

JAAS

‰La sécurité en Java EE est basé sur Java Authentication and Authorization Service(JAAS) qui est inclus dans Java SE (voir cours sur la sécurité en Java pour plus de détails)

‰JAAS est centré sur l’utilisateur: il permet de donner des permissions en se basant sur l’utilisateur qui exécute le code

‰JAAS s’appuie sur la notion de modules de login qui permettent d’authentifier l’utilisateur en utilisant un certain mode (par exemple en consultant une base de données)

(5)

‰Nous allons tout d’abord étudier comment définir les rôles puis comment authentifier un utilisateur

‰Nous verrons enfin comment protéger des pages Web, puis comment restreindre l’accès à des méthodes Java

‰L’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 25 R. Grin Sécurité Java EE page 26

Déclaration 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 27

Annotations pour les rôles

‰On verra les annotations @RolesAllowed,

@PermitAllet @DenyAllpour protéger l’accès à des méthodes

‰@RolesAlloweddéclare automatiquement les rôles concernés

‰Dans des cas complexes, l’annotation

@DeclareRolespeut être utile pour utiliser le nom d’un rôle dans une classe, sans que le rôle ne soit déclaré par ailleurs

R. Grin Sécurité Java EE page 28

Annotation pour déclarer des rôles

‰L’annotation @DeclareRolespeut être mise sur un EJB ou un servlet, au niveau de la classe

‰Elle peut prendre en paramètre un nom de rôle ou une liste de noms de rôle (entourée par des accolades)

‰La casse (majuscules – minuscules) est significative dans les noms de rôle

R. Grin Sécurité Java EE page 29

Exemples

‰@Stateless

@DeclareRoles("admin") public class MonBean { ... }

‰@Stateless

@DeclareRoles({"admin", "membre", "visiteur"}) public class MonBean {

@Resource

private SessionContext sc;

public void m() {

if (sc.isCallerInRole("membre") ...

}

R. Grin Sécurité Java EE page 30

(6)

Balise pour déclarer des rôles

‰Plusieurs balises<security-role>peuvent être mises directement sous la balise racine (web-app, ejb-jarouapplication)

‰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 31

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 EE

‰S’il réutilise son module dans plusieurs

applications, un nom de rôle peut avoir un autre nom dans les autres modules

‰Avec 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 32

Richard Grin Sécurité Java EE page 33

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

R. Grin Sécurité Java EE page 34

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’authentifier

‰Le plus souvent l’utilisateur s’authentifie en tapant son login et son mot de passe pour l’application dans un formulaire

‰Un certificat peut aussi être utilisé pour l’authentification (mode CLIENT-CERT), à la place du login/mot de passe

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’authentification

n<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

(7)

Exemple

<login-config>

<auth-method>BASIC</auth-method>

<realm-name>candidatures</realm-name>

</login-config>

R. Grin Sécurité Java EE page 37

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’application

‰Ce 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 38

Autres modes d’authentification

‰Plusieurs autres modes d’authentification, en plus du mode par défaut BASIC:

nFORM: utilisation d’un formulaire écrit par le développeur dans une page Web pour obtenir le login et le mot de passe

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

nCLIENT-CERT: utilisation d’un certificat

R. Grin Sécurité Java EE page 39

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 40

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 41

Mode FORM - formulaire de login

‰Si on choisit le mode FORM, le formulaire écrit par le développeur a des contraintes de nom pour

nl’action exécutée lorsque le formulaire est soumis (j_security_check)

nles 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 42

(8)

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 43

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 44

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 45

‰La méthode que l’on vient de voir est la façon la plus simple de filtrer les accès à une application

‰Elle 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 46

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 HttpServletRequestpour s’authentifier auprès du container (lance une

ServletExceptionsi déjà connecté ou mauvais login/mot de passe).

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>

(9)

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 login

‰Pour avoir l’URI de la page que voulait l’utilisateur, il faut utiliser l’attribut de la requête RequestDispatcher.FORWARD_REQUEST_URI

‰Merci à BalusC (expert JSF) pour l’information

R. Grin Sécurité Java EE page 49

Utilisation login – backing bean

@ManagedBean

@ViewScoped public class Login {

private String login, mdp;

private String uri;

@PostConstruct public void init() {

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

}

R. Grin Sécurité Java EE page 50

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 51

Déconnexion

‰L’authentification de l’utilisateur est valable pour toute la session de travail HTTP

‰Avec le mode d’authentification FORM, il est possible de faire sortir l’utilisateur de la session de travail avec la méthode logout()de la classe HttpServletRequest

‰Cette 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éconnecter

‰Un exemple d’utilisation est donné dans la section

« Code Java pour la sécurité » de ce support

R. Grin Sécurité Java EE page 52

SSL

‰Les login et mot de passe seront passés en clair sur le réseau

‰Il est possible d’utiliser SSL pour les protéger

‰Voir la section « Protection des pages Web »

R. Grin Sécurité Java EE page 53

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’application

‰La section « Sécurité avec GlassFish » donne un exemple d’utilisation du serveur GlassFish

R. Grin Sécurité Java EE page 54

(10)

Changer l’id d’une session

‰Pour éviter certaines formes de piratage, il peut être nécessaire de changer l’id d’une session en cours de session

‰Servlet 3.1 facilite ce changement de id avec :

nla méthode String changeSessionId() dans HttpServletRequestretourne le nouvel id de la session

nune interface écouteur

HttpSessionIdListenerqui est prévenue quand l’id de la session change

R. Grin Sécurité Java EE page 55

‰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ôle

‰Ensuite, il est montré comment configurer GlassFish pour les parties qui dépendent du serveur d’application

R. Grin Sécurité Java EE page 56

Protection des pages Web

R. Grin Sécurité Java EE page 57 R. Grin Sécurité Java EE page 58

Utilité

‰Le plus souvent des pages Web (définies par des URL) ne doivent être accessibles que par certains utilisateurs ou dans certaines circonstances

‰Cette section explique comment restreindre l’accès d’une partie des pages d’une application à certains utilisateurs

Erreurs HTTP pour la sécurité

‰Lorsqu’un utilisateur veut accéder à une page protégée, il peut arriver les erreurs suivantes :

nerreur HTTP 401, Unauthorized, si l’utilisateur ne fournit pas les credentials(le plus souvent le bon mot de passe)

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

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’application

‰Il est simple de grouper les pages à protéger dans un ou plusieurs répertoires et de filtrer l’accès à ces répertoires

‰Pour les cas plus complexes de filtrage, il est possible de coder le filtrage directement dans le code Java de l’application

(11)

Déclaration des protections

‰La protection est déclarée dans le fichier web.xml par 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 @HttpConstraintcontenue dans une annotation @ServletSecurity

R. Grin Sécurité Java EE page 61

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 62

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 63

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 64

<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 :

ncommence par / et se termine par /* (toute page située sous le répertoire qui précède « /* », à n’importe quelle profondeur

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

ncommence par / et ne comporte pas de *

R. Grin Sécurité Java EE page 65

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 66

(12)

<http-method>

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

‰Si cette balise est présente, la protection ne concerne que la méthode indiquée (GET et POST pour l’exemple suivant)

R. Grin Sécurité Java EE page 67

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 68

<http-method> - erreur à éviter

‰Si une balise est présente, la protection ne concerne que la méthode indiquée (ici GET)

‰Une erreur serait de croire que l’accès est protégé pour les autres méthodes ; il faut donc écrire une autre contrainte de sécurité qui interdit les autres méthodes en utilisant éventuellement la balise <http-method-omission>

‰Servlet 3.1 facilite ceci avec

<deny-uncovered-http-methods/>

R. Grin Sécurité Java EE page 69

Exemple – avant Servlet 3.1

‰Il faut ajouter la contrainte suivante :

<security-constraint>

<web-resource-collection>

<web-resource-name>r1</web-resource-name>

<url-pattern>/liste.xhtml</url-pattern>

<http-method-omission>GET</http-method-omission>

<http-method-omission>POST</http-method-omission>

</web-resource-collection>

<auth-constraint/>

</security-constraint>

R. Grin Sécurité Java EE page 70

Exemple – depuis Servlet 3.1

‰Il suffit de modifier la 1èrecontrainte ainsi :

<deny-uncovered-http-methods/>

<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>

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ées

‰Si 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>

(13)

Attention, pas de forward interne !

‰Un forward interne au serveur (méthode forward de 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 73

<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és

‰« ** » indique que tous les utilisateurs authentifiés sont acceptés (ajouté par Java EE 7)

‰S’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 74

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>**<role-name>

</auth-constraint>

</security-constraint>

R. Grin Sécurité Java EE page 75

<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 HTTPS

‰Elle contient une balise <transport-garantee>

dont la valeur peut être égale à NONE(valeur par défaut), CONFIDENTIALou INTEGRAL

R. Grin Sécurité Java EE page 76

Valeurs pour <transport-garantee>

‰CONFIDENTIAL: les données transmises ne peuvent être vues par des tiers

‰INTEGRAL: les données transmises ne peuvent être modifiées par des tiers

‰NONE: pas de protection particulière

‰En pratique, les 2 modes CONFIDENTIALet INTEGRALsont traités de la même façon par les serveurs d’application (utilisation de HTTPS)

‰Il est déconseillé de repasser en mode « normal » après être passé en mode « SSL » ; si on veut le faire tout de même, il est nécessaire d’écrire du code

R. Grin Sécurité Java EE page 77

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 78

(14)

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 79

Exemple 1

@WebServlet("/monurl")

@ServletSecurity(

@HttpConstraint(rolesAllowed={"r1", "r2"})) public class MaServlet extends HttpServlet

R. Grin Sécurité Java EE page 80

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

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 81

Protéger les méthodes des EJB

R. Grin Sécurité Java EE page 82

Par déclaration

‰Par défaut, toutes les méthodes sont accessibles à tous les utilisateurs

‰Il est possible de restreindre l’accès

navec une annotation

navec les fichiers de déploiement XML

‰Les fichiers XML l’emportent sur les annotations

Annotation @RolesAllowed

‰Annote une méthode ou une classe (concerne alors toutes les méthodes de la classe) protégée

‰En paramètre, un seul rôle ou plusieurs rôles de type Stringentourés d’accolades (les

utilisateurs ayant un des rôles peuvent utiliser la méthode ou la classe) :

@RolesAllowed("role1")

@RolesAllowed({ "role1", "role2" })

(15)

Annotation @PermitAll

‰Peut annoter une classe ou une méthode ; elle indique que toutes les méthodes de la classe annotée, ou la méthode annotée, sont autorisées à tous les utilisateurs

‰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 85

Annotation @DenyAll

‰Ne peut annoter qu’une méthode ; elle indique que la méthode annotée n’est accessible par aucun utilisateur

‰Cette annotation est rarement utilisée car la méthode annotée ne pourra pas être utilisée à l’intérieur d’un container Java EE

R. Grin Sécurité Java EE page 86

R. Grin Sécurité Java EE page 87

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>

R. Grin Sécurité Java EE page 88

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 89

Méthodes non protégées

‰Certaines méthodes sont autorisées à tous (<unchecked/>):

<method-permission>

<unchecked/>

<method>

<ejb-name>Compte</ejb-name>

<method-name>getNames</method-name>

</method>

R. Grin Sécurité Java EE page 90

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>

(16)

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éthode

‰Exemple :

@RunAs("admin")

‰Même utilité que le « suid » d’Unix : donner temporairement une autorisation à un utilisateur

R. Grin Sécurité Java EE page 91 R. Grin Sécurité Java EE page 92

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 93

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-identitypour 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>

AccessLocalException

‰Cette exception du paquetage javax.ejb est levée si une méthode est appelée alors que les autorisations ne sont pas suffisantes

R. Grin Sécurité Java EE page 94

Code Java pour la sécurité

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 souple

‰Dans ces cas, on peut écrire du code Java qui prend en compte les cas particuliers

‰L’exemple suivant montre comment distinguer des utilisateurs qui ont le même rôle dans une application JSF

(17)

R. Grin Sécurité Java EE page 97

Cas d’utilisation

‰Dans une application qui gère des formations, les utilisateurs doivent ouvrir un compte

‰Ce compte leur donne le rôle « etudiant » qui leur permet de s’inscrire à des cours et de participer à des forums

‰Cependant 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 bean peut contenir

‰On verra ensuite comment obtenir les mêmes informations dans une méthode d’un EJB session

R. Grin Sécurité Java EE page 98

R. Grin Sécurité Java EE page 99

Nom de l’utilisateur connecté

‰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();

R. Grin Sécurité Java EE page 100

Nom de l’utilisateur connecté avec CDI

‰CDI fournit un bean de type java.security.Principal; il suffit de l’injecter dans un backing bean (ou ailleurs) pour récupérer le nom de l’utilisateur connecté (ANONYMOUS si l’utilisateur ne s’est pas authentifié)

‰Exemple :

@Named @RequestScoped public class Bean {

@Inject

private Principal principal;

public String getNomUtilisateur() { return principal.getName();

}

Classe ExternalContext

‰Cette classe du paquetage

javax.faces.contextpermet 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 101 R. Grin Sécurité Java EE page 102

Méthodes de ExternalContext

‰boolean isUserInRole(String nomRole) retourne truesi celui qui appelle la méthode remplit bien le rôle passé en paramètre

‰java.security.Principal

getUserPrincipal()permet d’avoir le principal de celui qui appelle la méthode, ce qui permet de distinguer des utilisateurs qui ont le même rôle

‰Object getRequest()récupère la requête en cours (casteren

javax.servlet.http.HttpServletRequest)

(18)

Exemple avec JSF

...

String login = request.getRemoteUser();

if (<condition sur login>) {

FacesContext.getCurrentInstance() .getExternalContext()

.redirect(autrePage);

} ...

R. Grin Sécurité Java EE page 103

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 104

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.EJBContext

‰Cette interface est implémentée par la classe javax.ejb.SessionContext

‰On peut obtenir une instance de SessionContext en l’injectant dans un EJB session :

@Resource

private SessionContext contexte;

R. Grin Sécurité Java EE page 105

Méthodes de EJBContext

‰EJBContextcontient des méthodes liées à l’authentification des utilisateurs :

nPrincipal getCallerPrincipal()

nboolean 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 106

Exemple

// Méthode interdite à certains utilisateurs String login =

contexte.getCallerPrincipal().getName();

if (condition sur login) {

// l’utilisateur n’a pas le droit // de faire exécuter ce traitement throw new TrucException(...);

}

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

Configuration de GlassFish

(19)

Mode de configuration

‰GlassFish peut être configuré

ndu côté du serveur : avec la console d’administration ou avec la commande asadmin

nen 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 109

Console d’administration de GlassFish

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

‰Exemple :

http://localhost:4848

R. Grin Sécurité Java EE page 110

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 ; « asadmin commande --help » affiche une aide sur une commande)

R. Grin Sécurité Java EE page 111

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 sortir

‰On peut aussi lancer un script qui contient des commandes par « asadmin multimode --file script.txt »

R. Grin Sécurité Java EE page 112

Si GlassFish ne veut plus démarrer

‰Il peut s’agir d’un problème de configuration

‰A essayer :

nAller 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

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

nSi 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 113

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 114

(20)

Affecter les rôles avec GlassFish

‰La manière dont un rôle est associé à un utilisateur dépend du serveur d’application

‰GlassFish (et Tomcat) définit des groupes d’utilisateurs

‰On peut affecter un ou plusieurs rôles à un groupe ou à un utilisateur

‰Pour 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 115

Indiquer une correspondance avec un rôle

‰Pour indiquer la correspondance entre les groupes (ou les utilisateurs) et les rôles, 2 possibilités :

nutiliser un fichier de déploiement de l’application particulier à GlassFish pour donner les

correspondances entre groupes et rôles

nutiliser 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èrepossibilité)

R. Grin Sécurité Java EE page 116

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 117

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 118

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ôles

‰Pendant le développement il ne faut donc pas oublier de redéployer l’application après un changement de statut de cette activation

Par défaut, principal = rôle

‰Avec la commande asadmin :

asadmin set server-config.security-service.activate-default- principal-to-role-mapping=true

asadmin set server-config.security-service.mapped- principal-class=CustomPrincipalImplClass

‰Avec le menu de la console d’administration : Configuration > server-config > Securité > Cocher la case Default Principal To Role Mapping (en français : Mise en correspondance par défaut des principaux avec des rôles)

(21)

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 standard

‰GlassFish et Tomcat utilisent pour cela la notion de domaine (realmen anglais) qui correspond au domaine utilisée dans la balise <realm-name>

de la balise <login-config>

R. Grin Sécurité Java EE page 121

Domaine de sécurité

‰Dans GlassFish il y a les types de realmssuivants :

nfile(informations dans un simple fichier ; domaine par défaut)

njdbc(dans des tables d’un SGBDR)

nldap(utilise un registre LDAP)

ncertificate(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 122

Créer un domaine de sécurité

‰asadmin create-auth-realm permet de créer un realm

‰On 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 123

‰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 124

É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 125

Structure des tables

‰La table des utilisateurs doit avoir

nune colonne qui contient le nom de login

n 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 avoir

nune colonne qui contient le nom d’un groupe

nune colonne qui contient un nom de login

‰Ces tables peuvent avoir d’autres colonnes

R. Grin Sécurité Java EE page 126

(22)

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 127

Exemple de données

‰Dans la table des groupes : toto, groupe1

toto, groupe2 admin, admin

pour indiquer que toto appartient aux groupes groupe1 et groupe 2 et admin appartient au groupe admin

R. Grin JSF page 128

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

‰L’exemple suivant est le cas fréquent où un groupe est identifié par un id non significatif et où la correspondance entre un groupe et un login utilise cet id et pas le nom du groupe ; il faut créer une vue qui fera correspondre un login et un nom de groupe, et qui sera utilisée pour la définition du domaine de sécurité

R. Grin Sécurité Java EE page 129

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-groupe

‰Vue v_groupe_utilisateurqui va servir comme

« table » des groupes : create view v_groupe_utilisateur as select login, nom_groupe from groupe join groupe_utilisateur

on groupe.id_groupe = groupe_utilisateur.id_groupe

R. Grin Sécurité Java EE page 130

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’application

‰Il faut commencer par créer un pool de

connexions JDBC puis créer la source de données en utilisant ce pool de connexions

‰2 possibilités :

navec la console d’administration de GlassFish

navec la commande asadmin

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 JDBC

‰Avec asadmin create-jdbc-connection

‰Exemple asadmin :

asadmin create-jdbc-connection-pool --

datasourceclassname oracle.jdbc.pool.OracleDataSource -- restype javax.sql.DataSource --property

user=dbuser:password=mdpdb:url="jdbc:oracle\:thin\:@loca lhost\:1521\:ORCL" monpool

(23)

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 suivants

‰Avec les menus de la console d’administration : Ressources > JDBC > Resources JDBC

‰Avec asadmin create-jdbc-resource

‰Exemple :

asadmin create-jdbc-resource --connectionpoolid monpool jdbc/masource

R. Grin Sécurité Java EE page 133

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

‰Console d’administration de GlassFish

‰Configurations > server-config > Sécurité >

Domaines

‰Cliquer Nouveau

‰Nom : candidatures

‰Nom de classe : celle qui se nomme JDBCRealm

‰Il s’affiche des propriétés qu’il faut renseigner (éviter de taper des lettres accentuées ; problèmes possibles)

R. Grin JSF page 134

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

‰Contexte de JAAS : jdbcRealm

‰JNDI : 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 : LOGIN

‰Colonne de mot de passe : MOT_DE_PASSE

‰Table de groupes : GROUPE

‰Colonne de nom de groupe : NOM_GROUPE

R. Grin JSF page 135

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

‰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) ; pour Hex qui est la valeur par défaut, la chaîne de caractères sera de longueur 32 pour MD5 et de longueur 64 pour SHA256

R. Grin JSF page 136

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

‰Le charset indique quel codage des caractères est utilisé pour convertir en byte[] un mot de passe tapé par l’utilisateur, pour lui appliquer ensuite la fonction de hachage ; par défaut c’est le codage par défaut du système (UTF-8 le plus souvent)

R. Grin JSF page 137

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 138

Références

Documents relatifs

Car la page en question, elle aussi, prend l'apparence d'une page web de la banque imitée (logo, couleurs, etc.) mais les informations que vous transmettez via cette page web ne

J’ai choisi Chrome comme exemple parce qu’il est le navigateur le plus utilisé mais le moins sûr. Attention: avant d’aller à l’étape 7, il vaut mieux d’abord parcourir les

30 jours avant l’échéance du délai de validité, l’ordinateur de la douane établi automati- quement un nouveau certificat (certificat suivant) et le transmet soit à la personne

Ce guide rédigé par la Direction de la sécurité et de la conformité en matière de transport commercial des Transports de l’Ontario a pour but d’aider les entreprises de

Si le professeur juge qu’il y a des circonstances exceptionnelles pour justifier le retard, le professeur et l'étudiant(e) conviendront d’un arrangement (travail supplémentaire,

L'option -r supprime aussi le répertoire personnel et les fichiers de l'utilisateur La commande supprime toute trace de l'utilisateur dans le fichier de configuration /etc/passwd

Cet avis a pour objectif d’informer les médecins dans nos centres d’implantation européens de la possibilité d’un problème de synchronisation de la valve mécanique

• Inspection visuelle relative à l’inspection des dommages du câble moteur incluse dans le manuel d’utilisation du Système d’Assistance Circulatoire CentriMag et dans le