Commit d5d1cc9a32683f13eb8715358f2486cd25ac1d6b

Authored by Rémi Emonet
1 parent ec2b535539
Exists in master

...

Showing 2 changed files with 436 additions and 2 deletions

cours-06.html View file @ d5d1cc9
  1 +<!DOCTYPE html>
  2 +<html>
  3 + <head>
  4 + <meta charset="utf-8">
  5 + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  6 +
  7 + <title>Programmation Web Avancée   Security, javascript</title>
  8 + <meta name="cours-n" content="6">
  9 +
  10 + <meta name="author" content="Rémi Emonet">
  11 + <meta name="venue" content="PWA M1 DSC">
  12 + <meta name="date" content="2017">
  13 + <meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien">
  14 +
  15 + <style type="text/css">
  16 + .slide.densish>ul {font-size: 70%;}
  17 + .commented-fs p {margin: 1em; }
  18 + </style>
  19 +
  20 + <!--
  21 + <script src="deck.js/extensions/includedeck/load.js"></script>
  22 + <script src="extensions/slides-dev.js"></script>
  23 + -->
  24 + <script src="extensions/deck-packed.js"></script>
  25 + <script src="extensions/slides.js"></script>
  26 + <script>go()</script>
  27 + </head>
  28 +
  29 +<body>
  30 +
  31 +<div class="deck-container">
  32 +
  33 + <div class="deck-loading-splash" style="background: black; color: chartreuse;"><span class="vcenter" style="font-size: 30px; font-family: Arial; ">Please wait, while our marmots are preparing the hot chocolate…</span></div>
  34 +
  35 +<section class="smart">
  36 +
  37 +# @chunk: chunks/title.md
  38 +
  39 +# Questions ? <br/> Commentaires ? {no-print}
  40 +
  41 +# @chunk: chunks/objectives.md
  42 +
  43 +## Programmation Web Avancée <span>{var-cours-n}</span> : Plan {#plan overview}
  44 +- Re? Injection de Dépendances {di}
  45 +- Re? Persistence et JPA {jpaetc}
  46 +- Server-side : HTTPS {https}
  47 +- Server-side : Spring Security {security}
  48 +- Server-side : gestion d'utilisateurs {jpasecu}
  49 +- Javascript {rappeljs}
  50 +# @copy:#plan
  51 +
  52 +
  53 +<!-- ################################### -->
  54 +# @copy:#plan: %+class:inred: .di
  55 +
  56 +# <a href="cours-05.html#slide-56" target="_blank">slides précédents</a>
  57 +
  58 +
  59 +<!-- ###################### -->
  60 +# @copy:#plan: %+class:inred: .jpaetc
  61 +
  62 +# <a href="cours-05.html#slide-65" target="_blank">slides précédents</a>
  63 +
  64 +# Keeping Our Data! <br/> Tuning `application.properties{dense}`
  65 +
  66 +## What Did We Just Do? {libyli}
  67 +- Changing project configuration
  68 + - to override default configuration
  69 + - adding key=value properties in `application.properties`
  70 +- Using a file database (instead of solely in-memory)
  71 + - `spring.datasource.url=jdbc:h2:/tmp/mytestdb`
  72 +- Stopped dropping (and recreating) the database everytime
  73 + - `spring.jpa.hibernate.ddl-auto=none`
  74 +- NB about previous point
  75 + - in case one need to re-create the databse (schema update)
  76 + - the line can be remove
  77 + - or, use `spring.jpa.hibernate.ddl-auto=create-drop`
  78 +- Some properties
  79 + - `spring.datasource.password`, `spring.datasource.username`
  80 + - `server.port`
  81 + - and <a href="http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_blank">WAY more</a>
  82 +
  83 +
  84 +
  85 +
  86 +
  87 +
  88 +
  89 +
  90 +<!-- ################################### -->
  91 +# @copy:#plan: %+class:inred: .https
  92 +
  93 +# HTTPS {no-print}
  94 +
  95 +## HTTPS {libyli}
  96 +- Les communication HTTP sont non-sécurisées
  97 +- Un service en ligne doit utiliser HTTPS/SSL
  98 +- Comment configurer HTTPS
  99 + - générer certificate, au choix
  100 + - self-signed
  101 + - signé par <a href="https://letsencrypt.org/" target="_blank">https://letsencrypt.org/</a> (automatisable)
  102 + - signé par une autre autorité (e.g., video <a href="https://www.gandi.net/ssl" target="_blank">https://www.gandi.net/ssl</a>)
  103 + - configurer le serveur ou l'application
  104 + - <a href="http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-configure-ssl" target="_blank">configure SSL in Spring</a>
  105 +```
  106 +server.port=8443
  107 +server.ssl.key-store=classpath:keystore.jks
  108 +server.ssl.key-store-password=secret
  109 +server.ssl.key-password=another-secret
  110 +{slide}
  111 +```
  112 +- NB : alternative
  113 + - avoir une application HTTP
  114 + - déployer un serveur façade qui gère la communication HTTPS (e.g., <a href="http://webapp.org.ua/sysadmin/setting-up-nginx-ssl-reverse-proxy-for-tomcat/" target="_blank">nginx ssl</a> ou heroku, ...)
  115 +
  116 +# Demo ou Visite ?
  117 +
  118 +
  119 +<!-- ################################### -->
  120 +# @copy:#plan: %+class:inred: .security
  121 +
  122 +## Spring Security {libyli}
  123 +- `spring-boot-starter-security` dans le `pom.xml`
  124 + - gestion de l'authentification des utilisateurs
  125 + - restrictions d'accès
  126 + - redirection vers une page de login si nécessaire
  127 +- Besoin de créer une class Java pour la configuration
  128 + - extend `WebSecurityConfigurerAdapter`
  129 + - annotée avec `@Configuration` and `@EnableWebMvcSecurity`
  130 + - une méthode: `configure(HttpSecurity http)`
  131 + - choisir quelles urls sont public/private
  132 + - choisir les urls de login/logout, etc
  133 + - configuration du back-end d'authentification
  134 + - une méthode annotée avec `@Inject`
  135 + - qui prends `AuthenticationManagerBuilder` comme paramètre
  136 + - choisir où/comment sont stockés les utilisateurs
  137 + - permet aussi de créer des utilisateurs de test
  138 +- Guide Spring : <a href="https://spring.io/guides/gs/securing-web/" target="_blank">https://spring.io/guides/gs/securing-web/</a>
  139 +- Username grâce à un paramètre de type `Authentication`
  140 +
  141 +## Spring Security : Configuration Typique {libyli}
  142 +```
  143 +@Configuration
  144 +@EnableWebMvcSecurity
  145 +public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  146 +
  147 + @Override
  148 + protected void configure(HttpSecurity http) throws Exception {
  149 + http.authorizeRequests()
  150 + .antMatchers("/info", "/").permitAll()
  151 + .anyRequest().authenticated() //.hasAnyRole("ADMIN")
  152 + .and().formLogin().permitAll()
  153 + .and().logout().permitAll();
  154 + }
  155 +
  156 + @Override
  157 + protected void configure(AuthenticationManagerBuilder auth) {
  158 + auth.inMemoryAuthentication()
  159 + .withUser("robert").password("toto").roles("USER", "ADMIN")
  160 + .and().withUser("bob").password("toto").roles("USER");
  161 + }
  162 +}
  163 +{slide dense}
  164 +```
  165 +- Utilisateurs stockés en mémoire (test)
  166 +- Comprendre roles/authorities <a href="http://stackoverflow.com/questions/19525380/difference-between-role-and-grantedauthority-in-spring-security/19542316#19542316" target="_blank">(on stack overflow)</a>
  167 +
  168 +# Demo ou Visite ? {commented-fs}
  169 +
  170 +À partir de cette configuration, 2 utilisateurs existent.
  171 +Seules les pages `/` et `/info` sont accessible par les utilisateurs non connectés.
  172 +Toute autre page renvoie vers un formulaire de login.
  173 +
  174 +## Spring Security: redéfinir la page login, etc {libyli}
  175 +```java
  176 + ...
  177 + http.authorizeRequests()
  178 + .anyRequest().authenticated()
  179 + .and().formLogin().permitAll().loginPage("/MYlogin")
  180 + .and().logout().permitAll();
  181 +...
  182 +```
  183 +- \+ GET controller to route to a thymeleaf login page
  184 +```
  185 + ... xmlns:th="http://www.thymeleaf.org" ...
  186 +
  187 + <!-- the POST is handled by spring -->
  188 + <form th:action="@{/MYlogin}" method="post">
  189 + <input type="text" name="username"/>
  190 + <input type="password" name="password"/>
  191 + <div><input type="submit" value="Sign In"/></div>
  192 + </form>
  193 + ...
  194 + <!-- same here -->
  195 + <form th:action="@{/logout}" method="post">
  196 + <input type="submit" value="Sign Out"/>
  197 + </form>
  198 +{slide dense}
  199 +```
  200 +
  201 +<!-- ################################### -->
  202 +# @copy:#plan: %+class:inred: .jpasecu
  203 +
  204 +## Un `UserDetailsService` Maison {libyli}
  205 +- Objectifs
  206 + - remplacer la gestion en mémoire des utilisateurs
  207 + - choisir comment et où l'on sauve dans le profil utilisateur
  208 +- Principe
  209 + - faire une entité JPA pour les utilisateurs
  210 + - faire une repository pour y accéder
  211 + - implémenter un « user manager » (`UserDetailsService`)
  212 + - et **stocker correctement les mots de passe** (`BCryptPasswordEncoder`)
  213 + - enregistrer son `UserDetailsService` dans Spring
  214 + - dire à Spring quel encodeur on a utilisé pour les mots de passe
  215 + - utiliser JPA pour ajouter/modifier les utilisateurs
  216 +
  217 +
  218 +# Demo ou Visite ? {no-print}
  219 +
  220 +
  221 +
  222 +
  223 +
  224 +
  225 +<!-- ################################### -->
  226 +# @copy:#plan: %+class:inred: .rappeljs
  227 +
  228 +
  229 +
  230 +## JavaScript : Bases {libyli}
  231 +- Seul langage impératif dans le navigateur
  232 +- Surnom de ECMAScript
  233 +- Première version : 1995
  234 +- ECMAScript 6 (ES6): 17 juin 2015 <a href="http://kangax.github.io/compat-table/es6/" target="_blank">&rArr;</a> <a href="http://caniuse.com/#search=es6/" target="_blank">&rArr;</a>
  235 +- Pas de lien (fort) avec Java
  236 +- [Multi-paradigm](https://en.wikipedia.org/wiki/JavaScript): objet, impératif, fonctionnel, prototype
  237 +- Aussi hors du navigateur (sans DOM)
  238 + - Rhino, Nashorn (JSR 223: Scripting for the Java Platform)
  239 + - V8: NodeJS, MongoDB, Couchbase // &ne; couchdb
  240 +
  241 +## JavaScript dans le Navigateur {libyli}
  242 +- Avec un élément HTML `script`
  243 +- `<script></script>` avec un contenu
  244 +```html
  245 + ≺script>
  246 + alert("Hello World.");
  247 + ≺/script>
  248 +{slide}
  249 +```
  250 +- `<script src="..."></script>{dense}` pour inclure un fichier `.js`
  251 +```html
  252 + &lt;script src="myFile.js" />
  253 +{slide}
  254 +```
  255 +- Exécuté quand l'élément est parsé <a href="js-examples/include.html" target="_blank">&rArr;</a>
  256 +- Pour expérimentations : utiliser la console du navigateur
  257 +
  258 +
  259 +
  260 +
  261 +
  262 +
  263 +
  264 +## Syntaxe et Typage JS {libyli}
  265 +- Syntaxe ressemblant à C/Java
  266 +- Pas de typage statique (fonctions, variables)
  267 +- Tout est objet (y compris les types de base) `rrr = 3.14;`
  268 +- Accès dynamique au type via `typeof(rrr)`
  269 +- [Types par défauts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FOperators%2Ftypeof)
  270 + - `String` (ex `"hello"`, `'hello'`)
  271 + - `Number` (ex `12`, `42.10`)
  272 + - `Boolean` (ex `true`, `false`)
  273 + - `Function` (ex `function (a) { return a*a; }{}`)
  274 + - `Object` (pour les tableaux et les autres objets)
  275 +
  276 +## Variables et Portées JS {libyli}
  277 +- Variables locales aux fonctions, définies avec `var`
  278 + - comme si définie au début de la fonction
  279 + - &ne; C/Java : JS n'a pas de portée « bloc »
  280 +- portée
  281 + - portée fonction (= python, &ne; java)
  282 + - portée globale, gérée par l'environnement (navigateur, ...) // more later
  283 +- NB
  284 + - `null` est une valeur (`typeof(null) === 'object'`)
  285 + - variable non définie: `typeof(rrr) === 'undefined'`
  286 +
  287 +
  288 +## Objets JS (et JSON) {libyli}
  289 +- Les objets JavaScript sont des « maps »
  290 + - les clés sont des chaînes
  291 + - les valeurs sont de n'importe quels types
  292 +- Les objets JavaScript n'ont pas de classe (fixe)
  293 + - possibilité d'ajouter des propriétés dynamiquement
  294 + - possibilité d'enlever ou changer le type de propriétés
  295 +- Notation pour la création et l'accès
  296 +```javascript
  297 +var o = { first: 123,
  298 + "second": 456,
  299 + 'third': {firstname: "Bob", age: "99"} };
  300 +alert(o.first);
  301 +alert(o["first"]);
  302 +var k = "second";
  303 +alert(o[k]);
  304 +{slide dense}
  305 +```
  306 +- Représentation JSON (JavaScript Object Notation)
  307 + - proche de JavaScript, mais que des constantes, que des `"..."`
  308 + - guillemets obligatoires (ex, erreur avec `first` et `'third'` )
  309 +
  310 +
  311 +## Tableaux JS (et JSON) {libyli}
  312 +- Tableaux JavaScript
  313 + - type spécial d'objet JavaScript
  314 + - sucre syntaxique « syntactic sugar »
  315 + - possible en JSON
  316 +- Notation pour la création et l'accès
  317 +```javascript
  318 +var freshFruits = ["banana", "pear", "apple", "tomato"];
  319 +
  320 +alert(freshFruits[0]);
  321 +alert(freshFruits.length);
  322 +
  323 +freshFruits.push("blueberries")
  324 +alert(freshFruits.length);
  325 +
  326 +for (k in freshFruits) { // itère sur les clés
  327 + alert(freshFruits[k]);
  328 +}
  329 +{slide}
  330 +```
  331 +
  332 +
  333 +## Fonctions JS {libyli}
  334 +- Fonction nommée « classique » en JavaScript
  335 +```javascript
  336 +function toto(a,b) {
  337 + return a+b;
  338 +}
  339 +alert(toto(1,3));
  340 +{dense slide}
  341 +```
  342 +- Fonction JavaScript : objet de première classe
  343 +```javascript
  344 +var f = function(a) {
  345 + return a*a;
  346 +}
  347 +alert(f(2));
  348 +var squares = [1,2,3].map(f);
  349 +{dense slide firstorder}
  350 +```
  351 +- @anim: .firstorder>span:nth-of-type(4) | .firstorder>span:nth-of-type(5)
  352 +- Fonction anonyme
  353 +```javascript
  354 +var squares = [1,2,3].map(function(a) {
  355 + return a*a;
  356 +});
  357 +
  358 +setTimeout(function() { alert("Hello"); },
  359 + 3000);
  360 +{dense slide anonymous}
  361 +```
  362 +- @anim: .anonymous>span:nth-of-type(5), .anonymous>span:nth-of-type(6)
  363 +
  364 +
  365 +## Objets et Classes JS {libyli}
  366 +- JS n'est pas un langage orienté classe (Java)
  367 +- JS est un langage à prototype
  368 +- Très dynamique
  369 +- Attention à `this` (&ne; Java)
  370 + - un objet « contexte »
  371 + - pas nécessairement d'un type donné (comme la classe)
  372 +- Plus flexible que les langages à classes
  373 +- Le mot clé `class` arrive en ES6 ;-(
  374 +
  375 +
  376 +## ES6 (ES2015) {libyli}
  377 +- Syntaxe : class
  378 + - `constructor()`, `super()`
  379 + - `get`, `set`
  380 +- Syntaxes
  381 + - Modifieurs et portées de variables : const, var, val, let
  382 + - *Arrow Functions* et gestion du `this`
  383 + - Interpolation de string `\`Hello ${name}\``
  384 + - Propriétés : raccourcis, méthodes, prop. construire (`[ «» ] : «»`)
  385 + - Construction et déconstruction pour listes et objets (avec valeur par défaut et y compris en param)
  386 + - *Rest* et *Spread* avec `...` (y compris en paramètre, syntactic sugar pour `arguments`)
  387 + - Paramètres par défaut `a=2`
  388 +- Autres : modules, generator
  389 +- <a href="http://es6-features.org/" target="_blank">etc.</a>
  390 +
  391 +
  392 +
  393 +
  394 +
  395 +
  396 +</section>
  397 +
  398 + <!-- deck.status snippet -->
  399 + <p class="deck-status deck-progress-10"> <span class="deck-status-current"></span> / <span class="deck-status-total"></span> − <span class="var-author">will be replaced by the author</span> − <span class="var-title">will be replaced by the title</span></p>
  400 +
  401 + <a data-progress-size=": spe.top(15, 555); height: 45*designRatio; left: slide.right - 90*designRatio; width: 90*designRatio" class="ccby" href="http://en.wikipedia.org/wiki/Creative_Commons_license" title="This work is under CC-BY licence." target="_blank"></a>
  402 +
  403 + <a class="ujm" data-progress-size=": spe.top(15, 525); height: 65*designRatio; left: slide.left; width: 130*designRatio" target="_blank"></a>
  404 +
  405 +</div>
  406 +<!-- clicky Cla -->
  407 +<script type="text/javascript">
  408 +var clicky_site_ids = clicky_site_ids || [];
  409 +clicky_site_ids.push(100779706);
  410 +(function() {
  411 + var s = document.createElement('script');
  412 + s.type = 'text/javascript';
  413 + s.async = true;
  414 + s.src = '//static.getclicky.com/js';
  415 + ( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s );
  416 +})();
  417 +</script>
  418 +<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100779706ns.gif" /></p></noscript>
  419 +
  420 +
  421 +<!-- Histats.com START (aync)-->
  422 +<script type="text/javascript">var _Hasync= _Hasync|| [];
  423 +_Hasync.push(['Histats.start', '1,2767123,4,0,0,0,00010000']);
  424 +_Hasync.push(['Histats.fasi', '1']);
  425 +_Hasync.push(['Histats.track_hits', '']);
  426 +(function() {
  427 +var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true;
  428 +hs.src = ('http://s10.histats.com/js15_as.js');
  429 +(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs);
  430 +})();</script>
  431 +<noscript><a href="http://www.histats.com" target="_blank"><img src="http://sstatic1.histats.com/0.gif?2767123&101" alt="javascript hit counter" border="0"></a></noscript>
  432 +<!-- Histats.com END -->
  433 +</body>
  434 +</html>
... ... @@ -47,10 +47,10 @@
47 47 <a class="tile" href="cours-02.html">Slides 2 <br/> HTML+CSS</a>
48 48 <a class="tile" href="cours-03.html" style="font-size:80%;">Slides 3 <br/> MVC, Spring+Thymeleaf</a>
49 49 <a class="tile" href="cours-04.html">Slides 4 <br/> Projet, TP1</a>
50   - <a class="tile" href="cours-05.html">Slides 5 <br/> Thymeleaf, DI</a>
51   - <a class="tile" href="cours-05.html">Slides 5 <br/> Thymeleaf, DI</a>
  50 + <a class="tile" href="cours-05.html">Slides 5 <br/> Thymeleaf, DI, JPA</a>
52 51 <a class="tile" href="cours-git.html">Slides GIT <br/> (not so standalone)</a>
53 52 <a class="tile" href="raw/https-secu-utilisateurs.zip">Code <br/> (https, secu, users)</a>
  53 + <a class="tile" href="cours-06.html">Slides 6 <br/> DI, Security, JS</a>
54 54 </div>
55 55  
56 56 <h2>Code des séances</h2>