<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Programmation Web Avancée Security, javascript</title>
<meta name="cours-n" content="6">
<meta name="author" content="Rémi Emonet">
<meta name="venue" content="PWA M1 DSC">
<meta name="date" content="2017">
<meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien">
<style type="text/css">
.slide.densish>ul {font-size: 70%;}
.commented-fs p {margin: 1em; }
</style>
<!--
<script src="deck.js/extensions/includedeck/load.js"></script>
<script src="extensions/slides-dev.js"></script>
-->
<script src="extensions/deck-packed.js"></script>
<script src="extensions/slides.js"></script>
<script>go()</script>
</head>
<body>
<div class="deck-container">
<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>
<section class="smart">
# @chunk: chunks/title.md
# Questions ? <br/> Commentaires ? {no-print}
# @chunk: chunks/objectives.md
## Programmation Web Avancée <span>{var-cours-n}</span> : Plan {#plan overview}
- Re? Injection de Dépendances {di}
- Re? Persistence et JPA {jpaetc}
- Server-side : HTTPS {https}
- Server-side : Spring Security {security}
- Server-side : gestion d'utilisateurs {jpasecu}
- Javascript {rappeljs}
# @copy:#plan
<!-- ################################### -->
# @copy:#plan: %+class:inred: .di
# <a href="cours-05.html#slide-56" target="_blank">slides précédents</a>
<!-- ###################### -->
# @copy:#plan: %+class:inred: .jpaetc
# <a href="cours-05.html#slide-65" target="_blank">slides précédents</a>
# Keeping Our Data! <br/> Tuning `application.properties{dense}`
## What Did We Just Do? {libyli}
- Changing project configuration
- to override default configuration
- adding key=value properties in `application.properties`
- Using a file database (instead of solely in-memory)
- `spring.datasource.url=jdbc:h2:/tmp/mytestdb`
- Stopped dropping (and recreating) the database everytime
- `spring.jpa.hibernate.ddl-auto=none`
- NB about previous point
- in case one need to re-create the databse (schema update)
- the line can be remove
- or, use `spring.jpa.hibernate.ddl-auto=create-drop`
- Some properties
- `spring.datasource.password`, `spring.datasource.username`
- `server.port`
- and <a href="http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_blank">WAY more</a>
<!-- ################################### -->
# @copy:#plan: %+class:inred: .https
# HTTPS {no-print}
## HTTPS {libyli}
- Les communication HTTP sont non-sécurisées
- Un service en ligne doit utiliser HTTPS/SSL
- Comment configurer HTTPS
- générer certificate, au choix
- self-signed
- signé par <a href="https://letsencrypt.org/" target="_blank">https://letsencrypt.org/</a> (automatisable)
- signé par une autre autorité (e.g., video <a href="https://www.gandi.net/ssl" target="_blank">https://www.gandi.net/ssl</a>)
- configurer le serveur ou l'application
- <a href="http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-configure-ssl" target="_blank">configure SSL in Spring</a>
```
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
{slide}
```
- NB : alternative
- avoir une application HTTP
- 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, ...)
# Demo ou Visite ?
<!-- ################################### -->
# @copy:#plan: %+class:inred: .security
## Spring Security {libyli}
- `spring-boot-starter-security` dans le `pom.xml`
- gestion de l'authentification des utilisateurs
- restrictions d'accès
- redirection vers une page de login si nécessaire
- Besoin de créer une class Java pour la configuration
- extend `WebSecurityConfigurerAdapter`
- annotée avec `@Configuration` and `@EnableWebMvcSecurity`
- une méthode: `configure(HttpSecurity http)`
- choisir quelles urls sont public/private
- choisir les urls de login/logout, etc
- configuration du back-end d'authentification
- une méthode annotée avec `@Inject`
- qui prends `AuthenticationManagerBuilder` comme paramètre
- choisir où/comment sont stockés les utilisateurs
- permet aussi de créer des utilisateurs de test
- Guide Spring : <a href="https://spring.io/guides/gs/securing-web/" target="_blank">https://spring.io/guides/gs/securing-web/</a>
- Username grâce à un paramètre de type `Authentication`
## Spring Security : Configuration Typique {libyli}
```
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/info", "/").permitAll()
.anyRequest().authenticated() //.hasAnyRole("ADMIN")
.and().formLogin().permitAll()
.and().logout().permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
.withUser("robert").password("toto").roles("USER", "ADMIN")
.and().withUser("bob").password("toto").roles("USER");
}
}
{slide dense}
```
- Utilisateurs stockés en mémoire (test)
- 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>
# Demo ou Visite ? {commented-fs}
À partir de cette configuration, 2 utilisateurs existent.
Seules les pages `/` et `/info` sont accessible par les utilisateurs non connectés.
Toute autre page renvoie vers un formulaire de login.
## Spring Security: redéfinir la page login, etc {libyli}
```java
...
http.authorizeRequests()
.anyRequest().authenticated()
.and().formLogin().permitAll().loginPage("/MYlogin")
.and().logout().permitAll();
...
```
- \+ GET controller to route to a thymeleaf login page
```
... xmlns:th="http://www.thymeleaf.org" ...
<!-- the POST is handled by spring -->
<form th:action="@{/MYlogin}" method="post">
<input type="text" name="username"/>
<input type="password" name="password"/>
<div><input type="submit" value="Sign In"/></div>
</form>
...
<!-- same here -->
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
{slide dense}
```
<!-- ################################### -->
# @copy:#plan: %+class:inred: .jpasecu
## Un `UserDetailsService` Maison {libyli}
- Objectifs
- remplacer la gestion en mémoire des utilisateurs
- choisir comment et où l'on sauve dans le profil utilisateur
- Principe
- faire une entité JPA pour les utilisateurs
- faire une repository pour y accéder
- implémenter un « user manager » (`UserDetailsService`)
- et **stocker correctement les mots de passe** (`BCryptPasswordEncoder`)
- enregistrer son `UserDetailsService` dans Spring
- dire à Spring quel encodeur on a utilisé pour les mots de passe
- utiliser JPA pour ajouter/modifier les utilisateurs
# Demo ou Visite ? {no-print}
<!-- ################################### -->
# @copy:#plan: %+class:inred: .rappeljs
## JavaScript : Bases {libyli}
- Seul langage impératif dans le navigateur
- Surnom de ECMAScript
- Première version : 1995
- ECMAScript 6 (ES6): 17 juin 2015 <a href="http://kangax.github.io/compat-table/es6/" target="_blank">⇒</a> <a href="http://caniuse.com/#search=es6/" target="_blank">⇒</a>
- Pas de lien (fort) avec Java
- [Multi-paradigm](https://en.wikipedia.org/wiki/JavaScript): objet, impératif, fonctionnel, prototype
- Aussi hors du navigateur (sans DOM)
- Rhino, Nashorn (JSR 223: Scripting for the Java Platform)
- V8: NodeJS, MongoDB, Couchbase // ≠ couchdb
## JavaScript dans le Navigateur {libyli}
- Avec un élément HTML `script`
- `<script></script>` avec un contenu
```html
≺script>
alert("Hello World.");
≺/script>
{slide}
```
- `<script src="..."></script>{dense}` pour inclure un fichier `.js`
```html
<script src="myFile.js" />
{slide}
```
- Exécuté quand l'élément est parsé <a href="js-examples/include.html" target="_blank">⇒</a>
- Pour expérimentations : utiliser la console du navigateur
## Syntaxe et Typage JS {libyli}
- Syntaxe ressemblant à C/Java
- Pas de typage statique (fonctions, variables)
- Tout est objet (y compris les types de base) `rrr = 3.14;`
- Accès dynamique au type via `typeof(rrr)`
- [Types par défauts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FOperators%2Ftypeof)
- `String` (ex `"hello"`, `'hello'`)
- `Number` (ex `12`, `42.10`)
- `Boolean` (ex `true`, `false`)
- `Function` (ex `function (a) { return a*a; }{}`)
- `Object` (pour les tableaux et les autres objets)
## Variables et Portées JS {libyli}
- Variables locales aux fonctions, définies avec `var`
- comme si définie au début de la fonction
- ≠ C/Java : JS n'a pas de portée « bloc »
- portée
- portée fonction (= python, ≠ java)
- portée globale, gérée par l'environnement (navigateur, ...) // more later
- NB
- `null` est une valeur (`typeof(null) === 'object'`)
- variable non définie: `typeof(rrr) === 'undefined'`
## Objets JS (et JSON) {libyli}
- Les objets JavaScript sont des « maps »
- les clés sont des chaînes
- les valeurs sont de n'importe quels types
- Les objets JavaScript n'ont pas de classe (fixe)
- possibilité d'ajouter des propriétés dynamiquement
- possibilité d'enlever ou changer le type de propriétés
- Notation pour la création et l'accès
```javascript
var o = { first: 123,
"second": 456,
'third': {firstname: "Bob", age: "99"} };
alert(o.first);
alert(o["first"]);
var k = "second";
alert(o[k]);
{slide dense}
```
- Représentation JSON (JavaScript Object Notation)
- proche de JavaScript, mais que des constantes, que des `"..."`
- guillemets obligatoires (ex, erreur avec `first` et `'third'` )
## Tableaux JS (et JSON) {libyli}
- Tableaux JavaScript
- type spécial d'objet JavaScript
- sucre syntaxique « syntactic sugar »
- possible en JSON
- Notation pour la création et l'accès
```javascript
var freshFruits = ["banana", "pear", "apple", "tomato"];
alert(freshFruits[0]);
alert(freshFruits.length);
freshFruits.push("blueberries")
alert(freshFruits.length);
for (k in freshFruits) { // itère sur les clés
alert(freshFruits[k]);
}
{slide}
```
## Fonctions JS {libyli}
- Fonction nommée « classique » en JavaScript
```javascript
function toto(a,b) {
return a+b;
}
alert(toto(1,3));
{dense slide}
```
- Fonction JavaScript : objet de première classe
```javascript
var f = function(a) {
return a*a;
}
alert(f(2));
var squares = [1,2,3].map(f);
{dense slide firstorder}
```
- @anim: .firstorder>span:nth-of-type(4) | .firstorder>span:nth-of-type(5)
- Fonction anonyme
```javascript
var squares = [1,2,3].map(function(a) {
return a*a;
});
setTimeout(function() { alert("Hello"); },
3000);
{dense slide anonymous}
```
- @anim: .anonymous>span:nth-of-type(5), .anonymous>span:nth-of-type(6)
</section>
<!-- deck.status snippet -->
<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>
<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>
<a class="ujm" data-progress-size=": spe.top(15, 525); height: 65*designRatio; left: slide.left; width: 130*designRatio" target="_blank"></a>
</div>
<!-- clicky Cla -->
<script type="text/javascript">
var clicky_site_ids = clicky_site_ids || [];
clicky_site_ids.push(100779706);
(function() {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = '//static.getclicky.com/js';
( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s );
})();
</script>
<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100779706ns.gif" /></p></noscript>
<!-- Histats.com START (aync)-->
<script type="text/javascript">var _Hasync= _Hasync|| [];
_Hasync.push(['Histats.start', '1,2767123,4,0,0,0,00010000']);
_Hasync.push(['Histats.fasi', '1']);
_Hasync.push(['Histats.track_hits', '']);
(function() {
var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true;
hs.src = ('http://s10.histats.com/js15_as.js');
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs);
})();</script>
<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>
<!-- Histats.com END -->
</body>
</html>