Commit 6029d52bf459b596c1584e13c3c65cf0042898fd

Authored by Antoine Duquenoy
1 parent eba991ae

Spring Security opérationnel

Pour le moment tout le monde peut se créer un compte et se connecter au site avec. La page d'accueil affiche le pseudo de l'utilisateur.
Par la suite il faudra :
* fixer un admin en BDD
* autoriser la création de compte aux admins
* créer un rôle user classique
PFE06/src/main/java/com/PFE/ServerManager/Customer.java
1 package com.PFE.ServerManager; 1 package com.PFE.ServerManager;
2 2
3 import javax.persistence.*; 3 import javax.persistence.*;
  4 +import java.util.Set;
4 5
5 @Entity 6 @Entity
6 @Table(name = "customer") // NE PAS utiliser "User" car c'est un mot clef réservé pour PostgreSQL 7 @Table(name = "customer") // NE PAS utiliser "User" car c'est un mot clef réservé pour PostgreSQL
@@ -16,24 +17,31 @@ public class Customer{ @@ -16,24 +17,31 @@ public class Customer{
16 @Column(name = "password") 17 @Column(name = "password")
17 private String password; 18 private String password;
18 19
19 - @ManyToOne(cascade = CascadeType.ALL) 20 + @Column(name = "active")
  21 + private int active;
  22 +
  23 + @ManyToMany(cascade = CascadeType.ALL)
20 @JoinTable(name = "customer_role", joinColumns = @JoinColumn(name = "customer_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) 24 @JoinTable(name = "customer_role", joinColumns = @JoinColumn(name = "customer_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
21 - //private Set<Role> roles;  
22 - private Role role; 25 + private Set<Role> roles;
23 26
24 - public void setRole(Role role) {  
25 - this.role = role;  
26 - } 27 + public void setRoles(Set<Role> roles) { this.roles = roles; }
  28 + public Set<Role> getRoles() { return roles; }
27 29
28 public void setId(Integer id) { 30 public void setId(Integer id) {
29 this.customer_id = id; 31 this.customer_id = id;
30 } 32 }
  33 + public Integer getCustomer_id() { return customer_id; }
31 34
32 public void setPseudo(String pseudo) { 35 public void setPseudo(String pseudo) {
33 this.pseudo = pseudo; 36 this.pseudo = pseudo;
34 } 37 }
  38 + public String getPseudo() { return pseudo; }
35 39
36 public void setPassword(String password) { 40 public void setPassword(String password) {
37 this.password = password; 41 this.password = password;
38 } 42 }
  43 + public String getPassword() { return password; }
  44 +
  45 + public void setActive(int active) { this.active = active; }
  46 + public int getActive() { return active; }
39 } 47 }
40 \ No newline at end of file 48 \ No newline at end of file
PFE06/src/main/java/com/PFE/ServerManager/MainController.java
@@ -4,6 +4,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -4,6 +4,10 @@ import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.stereotype.Controller; 4 import org.springframework.stereotype.Controller;
5 import org.springframework.web.bind.annotation.*; 5 import org.springframework.web.bind.annotation.*;
6 import org.springframework.web.servlet.ModelAndView; 6 import org.springframework.web.servlet.ModelAndView;
  7 +import java.util.HashSet;
  8 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  9 +import org.springframework.security.core.context.SecurityContextHolder;
  10 +import org.springframework.security.core.Authentication;
7 11
8 @Controller 12 @Controller
9 public class MainController { 13 public class MainController {
@@ -14,9 +18,22 @@ public class MainController { @@ -14,9 +18,22 @@ public class MainController {
14 @Autowired 18 @Autowired
15 RoleRepository roleRepository; 19 RoleRepository roleRepository;
16 20
17 - @RequestMapping(value="/")  
18 - public String home(){  
19 - return "home"; 21 + @Autowired
  22 + BCryptPasswordEncoder bCryptPasswordEncoder;
  23 +
  24 + @GetMapping(value="/")
  25 + public String homeRedirection(){
  26 + return "redirect:home";
  27 + }
  28 +
  29 + @GetMapping(value="/home")
  30 + public ModelAndView home() {
  31 + ModelAndView modelAndView = new ModelAndView();
  32 + Authentication auth = SecurityContextHolder.getContext().getAuthentication();
  33 + Customer customer = customerRepository.findByPseudo(auth.getName());
  34 + modelAndView.addObject("customerName", customer.getPseudo());
  35 + modelAndView.setViewName("home");
  36 + return modelAndView;
20 } 37 }
21 38
22 @GetMapping(path="/registration") 39 @GetMapping(path="/registration")
@@ -24,20 +41,28 @@ public class MainController { @@ -24,20 +41,28 @@ public class MainController {
24 return "registration";//fait le lien automatiquement avec le page html du même nom //return "redirect:/...."; 41 return "registration";//fait le lien automatiquement avec le page html du même nom //return "redirect:/....";
25 } 42 }
26 43
  44 + @GetMapping(path="/denied")
  45 + public String denied() {
  46 + return "denied";
  47 + }
  48 +
27 @PostMapping(path="/registration") 49 @PostMapping(path="/registration")
28 public ModelAndView addNewUser(@RequestParam String pseudo, @RequestParam String password) { 50 public ModelAndView addNewUser(@RequestParam String pseudo, @RequestParam String password) {
29 //Model map, ModelAndView ou l'utilisation direct comme dans la méthode précédente sont 3 méthodes qui permettent d'envoyer des informations et donc de changer l'apparence d'une page 51 //Model map, ModelAndView ou l'utilisation direct comme dans la méthode précédente sont 3 méthodes qui permettent d'envoyer des informations et donc de changer l'apparence d'une page
30 ModelAndView modelAndView = new ModelAndView(); // il n'est peut être pas utile d'utiliser ModelAndView 52 ModelAndView modelAndView = new ModelAndView(); // il n'est peut être pas utile d'utiliser ModelAndView
31 Customer n = new Customer(); 53 Customer n = new Customer();
32 n.setPseudo(pseudo); 54 n.setPseudo(pseudo);
33 - n.setPassword(password); 55 + n.setPassword(bCryptPasswordEncoder.encode(password));
  56 + n.setActive(1);
34 Customer temp = customerRepository.findByPseudo(pseudo); 57 Customer temp = customerRepository.findByPseudo(pseudo);
35 58
36 - /*Role nRole = roleRepository.findByRole("ADMIN");  
37 - n.setRoles(new HashSet<Role>(Arrays.asList(nRole)));*/  
38 Role role = new Role(); // l'utilisation d'un role au lieu d'un tableau semble valide, ormis la première ligne de la table qui n'est pas utilisé 59 Role role = new Role(); // l'utilisation d'un role au lieu d'un tableau semble valide, ormis la première ligne de la table qui n'est pas utilisé
39 role.setRole("ADMIN"); 60 role.setRole("ADMIN");
40 - n.setRole(role); 61 +
  62 + HashSet<Role> hset = new HashSet<Role>();
  63 + hset.add(role);
  64 +
  65 + n.setRoles(hset);
41 66
42 if(temp != null) { 67 if(temp != null) {
43 modelAndView.addObject("ok", "l'utilisateur existe déjà"); 68 modelAndView.addObject("ok", "l'utilisateur existe déjà");
@@ -46,45 +71,24 @@ public class MainController { @@ -46,45 +71,24 @@ public class MainController {
46 else { 71 else {
47 modelAndView.addObject("ok", "l'utilisateur a bien été ajouté"); 72 modelAndView.addObject("ok", "l'utilisateur a bien été ajouté");
48 customerRepository.save(n); 73 customerRepository.save(n);
49 - } 74 + }
50 modelAndView.setViewName("registration"); 75 modelAndView.setViewName("registration");
51 return modelAndView; 76 return modelAndView;
52 } 77 }
53 78
54 @GetMapping(path="/login") 79 @GetMapping(path="/login")
55 - public ModelAndView login(){ 80 + public ModelAndView login() {
56 ModelAndView modelAndView = new ModelAndView(); 81 ModelAndView modelAndView = new ModelAndView();
57 modelAndView.setViewName("login"); 82 modelAndView.setViewName("login");
58 return modelAndView; 83 return modelAndView;
59 } 84 }
60 - //////// Ne fonctionne pas /////////  
61 - /*public String login() {  
62 - return "login"; //return "redirect:/...."; //to send a request to redirect the current page  
63 - }*/  
64 - /*  
65 - @PostMapping(path="/login")  
66 - public ModelAndView connexion(@RequestParam String pseudo, @RequestParam String password) {  
67 - // @RequestParam means it is a parameter from the GET or POST request  
68 - //the model Map is used by thymeleaf as a storage for values display on the html page, this is the same way for ModelAndView  
69 - ModelAndView modelAndView = new ModelAndView();  
70 - Customer temp = customerRepository.findByPseudo(pseudo);  
71 - if(temp != null) {  
72 - modelAndView.addObject("error", "vous etes autorisé à être sur cette page");  
73 - }  
74 - else{  
75 - modelAndView.addObject("error", "vous n'etes pas autorisé à être sur cette page");  
76 - }  
77 - modelAndView.setViewName("login");  
78 - return modelAndView;  
79 - }*/  
80 - //////////////////////////  
81 85
82 @GetMapping(path="/all") 86 @GetMapping(path="/all")
83 public @ResponseBody Iterable<Customer> getAllUsers() { 87 public @ResponseBody Iterable<Customer> getAllUsers() {
84 return customerRepository.findAll(); 88 return customerRepository.findAll();
85 } 89 }
86 90
87 - @RequestMapping(value="/success") 91 + @GetMapping(value="/success")
88 public String success(){ 92 public String success(){
89 return "success"; 93 return "success";
90 } 94 }
PFE06/src/main/java/com/PFE/ServerManager/Role.java
@@ -21,4 +21,8 @@ public class Role { @@ -21,4 +21,8 @@ public class Role {
21 public void setRole(String role) { 21 public void setRole(String role) {
22 this.role = role; 22 this.role = role;
23 } 23 }
  24 + public String getRole() { return role; }
  25 +
  26 + public void setRole_id(Integer role_id) { this.role_id = role_id; }
  27 + public Integer getRole_id() { return role_id; }
24 } 28 }
25 \ No newline at end of file 29 \ No newline at end of file
PFE06/src/main/java/com/PFE/ServerManager/SecurityConfig.java
@@ -6,6 +6,8 @@ import org.springframework.context.annotation.Configuration; @@ -6,6 +6,8 @@ import org.springframework.context.annotation.Configuration;
6 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 6 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
7 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 8 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  9 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  10 +import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
9 11
10 import javax.sql.DataSource; 12 import javax.sql.DataSource;
11 13
@@ -17,27 +19,38 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @@ -17,27 +19,38 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
17 DataSource dataSource; 19 DataSource dataSource;
18 20
19 @Autowired 21 @Autowired
  22 + private BCryptPasswordEncoder passwordEncoder;
  23 +
  24 + @Autowired
20 public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception { 25 public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
21 auth.jdbcAuthentication() 26 auth.jdbcAuthentication()
22 .dataSource(dataSource) 27 .dataSource(dataSource)
23 - .usersByUsernameQuery("select pseudo, password from customer where pseudo=?")  
24 - .authoritiesByUsernameQuery("select u.pseudo, r.role from customer u inner join customer_role ur on(u.customer_id=ur.customer_id) inner join role r on(ur.role_id=r.role_id) where u.pseudo=?"); 28 + .passwordEncoder(passwordEncoder)
  29 + .usersByUsernameQuery("select pseudo, password , active from customer where pseudo=?")
  30 + .authoritiesByUsernameQuery("select c.pseudo, r.role from customer c inner join customer_role cr on(c.customer_id=cr.customer_id) inner join role r on(cr.role_id=r.role_id) where c.pseudo=?");
25 } 31 }
26 32
27 @Override 33 @Override
28 protected void configure(HttpSecurity http) throws Exception { 34 protected void configure(HttpSecurity http) throws Exception {
29 http 35 http
30 .authorizeRequests() 36 .authorizeRequests()
31 - .antMatchers("/").permitAll() 37 + .antMatchers("/home").hasAuthority("ADMIN")
32 .antMatchers("/registration").permitAll() 38 .antMatchers("/registration").permitAll()
33 .antMatchers("/login").permitAll() 39 .antMatchers("/login").permitAll()
34 - //.antMatchers("/registration").hasRole("ADMIN").anyRequest().authenticated() 40 + .antMatchers("/denied").permitAll()
  41 + .anyRequest().authenticated()
35 .and() 42 .and()
36 .formLogin() 43 .formLogin()
37 - .loginPage("/login").failureUrl("/login?error=true").defaultSuccessUrl("/success") 44 + .loginPage("/login").failureUrl("/login?error=true")
  45 + .defaultSuccessUrl("/success")
  46 + .usernameParameter("pseudo")
  47 + .passwordParameter("password")
38 .and() 48 .and()
39 .logout() 49 .logout()
40 - .permitAll();  
41 - //http.exceptionHandling().accessDeniedPage("/403"); 50 + .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
  51 + .logoutSuccessUrl("/")
  52 + .and()
  53 + .exceptionHandling()
  54 + .accessDeniedPage("/denied");
42 } 55 }
43 } 56 }
44 \ No newline at end of file 57 \ No newline at end of file
PFE06/src/main/java/com/PFE/ServerManager/WebMvcConfig.java 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +package com.PFE.ServerManager;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  6 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7 +
  8 +@Configuration
  9 +public class WebMvcConfig implements WebMvcConfigurer {
  10 +
  11 + @Bean
  12 + public BCryptPasswordEncoder bCryptpasswordEncoder() {
  13 + return new BCryptPasswordEncoder();
  14 + }
  15 +
  16 +}
0 \ No newline at end of file 17 \ No newline at end of file
PFE06/src/main/resources/application.properties
@@ -8,9 +8,9 @@ spring.jpa.hibernate.ddl-auto=create @@ -8,9 +8,9 @@ spring.jpa.hibernate.ddl-auto=create
8 #"update" met à jour la base données 8 #"update" met à jour la base données
9 9
10 #Simon Postgres config : 10 #Simon Postgres config :
11 -spring.datasource.url=jdbc:postgresql://localhost:5432/sql_only 11 +spring.datasource.url=jdbc:postgresql://localhost:3306/sql_only
12 spring.datasource.username=postgres 12 spring.datasource.username=postgres
13 -spring.datasource.password=idalurf123 13 +spring.datasource.password=admin
14 14
15 #Antoine Postgres config : 15 #Antoine Postgres config :
16 #spring.datasource.url=jdbc:postgresql://localhost:3302/sql_only 16 #spring.datasource.url=jdbc:postgresql://localhost:3302/sql_only
PFE06/src/main/resources/data.sql
1 /* ce fichier doit être placé dans les ressources afin d'être utilisé */ 1 /* ce fichier doit être placé dans les ressources afin d'être utilisé */
2 INSERT INTO "role" VALUES (1,'ADMIN'); 2 INSERT INTO "role" VALUES (1,'ADMIN');
3 -/*INSERT INTO "customer" VALUES (10,1,'Feutrier','Simon');  
4 -INSERT INTO "customer" VALUES (11,1,'Duquenoy','Antoine'); 3 +/*
  4 +INSERT INTO "customer" VALUES (1,1,'Feutrier','Simon');
  5 +INSERT INTO "customer" VALUES (2,1,'Duquenoy','Antoine');
5 INSERT INTO "customer_role" VALUES (1,1); 6 INSERT INTO "customer_role" VALUES (1,1);
6 -INSERT INTO "customer_role" VALUES (2,1);*/  
7 \ No newline at end of file 7 \ No newline at end of file
  8 +INSERT INTO "customer_role" VALUES (2,1);
  9 +*/
8 \ No newline at end of file 10 \ No newline at end of file
PFE06/src/main/resources/templates/denied.html 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<!DOCTYPE html>
  2 +<html xmlns:th="http://www.thymeleaf.org">
  3 +<html lang="en">
  4 +<head>
  5 + <meta charset="UTF-8">
  6 + <title>Access Denied</title>
  7 +</head>
  8 +<body>
  9 + <h1>Access Denied !</h1>
  10 +
  11 + <form th:action="@{/login}" method="GET">
  12 + <button type="Submit">Se connecter</button>
  13 + </form>
  14 +
  15 +</body>
  16 +</html>
0 \ No newline at end of file 17 \ No newline at end of file
PFE06/src/main/resources/templates/home.html
@@ -6,7 +6,17 @@ @@ -6,7 +6,17 @@
6 <title>Page d'accueil</title> 6 <title>Page d'accueil</title>
7 </head> 7 </head>
8 <body> 8 <body>
9 -<a th:href="@{/login}">connexion</a>  
10 -<a th:href="@{/registration}">enregistrer des utilisateurs</a> 9 +
  10 + <a th:href="@{/login}">Connexion</a>
  11 + <a th:href="@{/registration}">Enregistrer des utilisateurs</a>
  12 +
  13 + <form th:action="@{/logout}" method="GET">
  14 + <button type="Submit">Logout </button>
  15 + </form>
  16 +
  17 +
  18 + <h1 th:utext="${customerName}"> est connecté(e) !</h1>
  19 +
  20 +
11 </body> 21 </body>
12 </html> 22 </html>
13 \ No newline at end of file 23 \ No newline at end of file
PFE06/src/main/resources/templates/login.html
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 </head> 6 </head>
7 <body> 7 <body>
8 <div> 8 <div>
9 - <h5>Ajouter de nouveaux utilisateurs :</h5> 9 + <h5>Se connecter :</h5>
10 <form th:action="@{/login}" method="POST"> 10 <form th:action="@{/login}" method="POST">
11 <div class="form1"> 11 <div class="form1">
12 <label for="username">User Name: </label> 12 <label for="username">User Name: </label>
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <label for="password">Password: </label> 16 <label for="password">Password: </label>
17 <input type="password" id="password" placeholder="Enter Password" name="password"/> 17 <input type="password" id="password" placeholder="Enter Password" name="password"/>
18 </div> 18 </div>
19 - <button type="submit">se connecter</button> 19 + <button type="submit">Se connecter</button>
20 </form> 20 </form>
21 <span th:utext="${error}"></span> 21 <span th:utext="${error}"></span>
22 <!--<div th:if="${param.ok}"> 22 <!--<div th:if="${param.ok}">