Commit 322c9502a32ebc9aeee8179c5eac890ca876211c

Authored by Julien Cartigny
1 parent 88ff471f

Ad Spring security support and validation

Showing 31 changed files with 309 additions and 492 deletions   Show diff stats
... ... @@ -36,15 +36,15 @@
36 36 <groupId>org.springframework.boot</groupId>
37 37 <artifactId>spring-boot-starter-web</artifactId>
38 38 </dependency>
39   - <!--dependency>
40   - <groupId>org.springframework.boot</groupId>
41   - <artifactId>spring-boot-starter-security</artifactId>
42   - </dependency-->
43 39 <dependency>
44 40 <groupId>org.springframework.boot</groupId>
45 41 <artifactId>spring-boot-starter-tomcat</artifactId>
46 42 <scope>provided</scope>
47 43 </dependency>
  44 + <dependency>
  45 + <groupId>org.springframework.boot</groupId>
  46 + <artifactId>spring-boot-starter-security</artifactId>
  47 + </dependency>
48 48 <dependency>
49 49 <groupId>org.springframework.boot</groupId>
50 50 <artifactId>spring-boot-starter-test</artifactId>
... ...
src/main/java/fr/plil/sio/web/mvc/Application.java
... ... @@ -2,11 +2,18 @@ package fr.plil.sio.web.mvc;
2 2  
3 3 import org.springframework.boot.SpringApplication;
4 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
  5 +import org.springframework.boot.builder.SpringApplicationBuilder;
  6 +import org.springframework.boot.web.support.SpringBootServletInitializer;
5 7  
6 8  
7 9 @SpringBootApplication
8   -public class Application {
  10 +public class Application extends SpringBootServletInitializer {
9 11 public static void main(String[] args) {
10 12 SpringApplication.run(Application.class, args);
11 13 }
  14 +
  15 + @Override
  16 + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
  17 + return application.sources(Application.class);
  18 + }
12 19 }
... ...
src/main/java/fr/plil/sio/web/mvc/ApplicationMvcConfiguration.java
1 1 package fr.plil.sio.web.mvc;
2 2  
3 3  
4   -import org.slf4j.Logger;
5   -import org.slf4j.LoggerFactory;
6 4 import org.springframework.boot.SpringBootConfiguration;
7 5 import org.springframework.context.annotation.Bean;
8   -import org.springframework.context.annotation.Scope;
9   -import org.springframework.context.annotation.ScopedProxyMode;
10   -import org.springframework.web.context.WebApplicationContext;
  6 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  7 +import org.springframework.security.crypto.password.PasswordEncoder;
11 8 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
12 9  
13 10 @SpringBootConfiguration
14 11 public class ApplicationMvcConfiguration extends WebMvcConfigurerAdapter {
15 12  
16   - private static final Logger logger = LoggerFactory.getLogger(ApplicationMvcConfiguration.class);
17   -
18   - @Bean
19   - @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode. TARGET_CLASS)
20   - public UserSession userSession() {
21   - logger.debug("new user session bean");
22   - return new UserSession();
23   - }
24   -
25   -/*
26 13 @Bean
27   - public CheckUserInterceptor checkUserInterceptor() {
28   - return new CheckUserInterceptor();
29   - }
30   -
31   - @Override
32   - public void addInterceptors(InterceptorRegistry registry) {
33   - CheckUserInterceptor interceptor = checkUserInterceptor();
34   - interceptor.setUserSession(userSession());
35   - registry.addInterceptor(interceptor);
  14 + public PasswordEncoder passwordEncoder() {
  15 + return new BCryptPasswordEncoder();
36 16 }
37   -*/
38 17 }
... ...
src/main/java/fr/plil/sio/web/mvc/ApplicationSecurityConfiguration.java 0 โ†’ 100644
... ... @@ -0,0 +1,44 @@
  1 +package fr.plil.sio.web.mvc;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  6 +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  7 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  8 +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  9 +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  10 +import org.springframework.security.core.userdetails.UserDetailsService;
  11 +import org.springframework.security.crypto.password.PasswordEncoder;
  12 +
  13 +import javax.annotation.Resource;
  14 +
  15 +@Configuration
  16 +@EnableWebSecurity
  17 +@EnableGlobalMethodSecurity(prePostEnabled = true)
  18 +public class ApplicationSecurityConfiguration extends WebSecurityConfigurerAdapter {
  19 +
  20 + @Resource
  21 + private PasswordEncoder passwordEncoder;
  22 +
  23 + @Resource
  24 + private UserDetailsService userDetailsService;
  25 +
  26 + @Override
  27 + protected void configure(HttpSecurity http) throws Exception {
  28 + http
  29 + .authorizeRequests()
  30 + .anyRequest().authenticated()
  31 + .and()
  32 + .formLogin()
  33 + .loginPage("/login")
  34 + .permitAll()
  35 + .and()
  36 + .logout()
  37 + .permitAll();
  38 + }
  39 +
  40 + @Autowired
  41 + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  42 + auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
  43 + }
  44 +}
0 45 \ No newline at end of file
... ...
src/main/java/fr/plil/sio/web/mvc/CheckUserInterceptor.java deleted
... ... @@ -1,45 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import org.slf4j.Logger;
4   -import org.slf4j.LoggerFactory;
5   -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
6   -
7   -import javax.annotation.Resource;
8   -import javax.servlet.http.HttpServletRequest;
9   -import javax.servlet.http.HttpServletResponse;
10   -import java.io.IOException;
11   -
12   -public class CheckUserInterceptor extends HandlerInterceptorAdapter {
13   -
14   - private static final Logger logger = LoggerFactory.getLogger(CheckUserInterceptor.class);
15   -
16   - @Resource
17   - private UserSession userSession;
18   -
19   - @Override
20   - public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
21   - Object handler) throws IOException {
22   -
23   - logger.debug("servlet path: " + request.getServletPath());
24   -
25   - if (request.getServletPath().equals("/login")) {
26   - logger.debug("access granted as path is /login");
27   - return true;
28   - }
29   -
30   - String username = userSession.getUsername();
31   -
32   - if (username != null) {
33   - logger.debug("authenticated");
34   - return true;
35   - } else {
36   - logger.debug("not authenticated");
37   - response.sendRedirect("login");
38   - return false;
39   - }
40   - }
41   -
42   - void setUserSession(UserSession userSession) {
43   - this.userSession = userSession;
44   - }
45   -}
src/main/java/fr/plil/sio/web/mvc/LoginController.java
1 1 package fr.plil.sio.web.mvc;
2 2  
3 3 import org.springframework.stereotype.Controller;
4   -import org.springframework.validation.BindingResult;
5 4 import org.springframework.web.bind.annotation.RequestMapping;
6 5 import org.springframework.web.bind.annotation.RequestMethod;
7 6 import org.springframework.web.servlet.ModelAndView;
8 7  
9   -import javax.annotation.Resource;
10   -
11 8 @Controller
12   -@RequestMapping(value = "/login")
13 9 public class LoginController {
14 10  
15   - @Resource
16   - private UserRepository userRepository;
17   -
18   - @Resource
19   - private UserSession userSession;
20   -
21   - @RequestMapping(method = RequestMethod.GET)
22   - public ModelAndView getLoginForm() {
23   - return new ModelAndView("login", "user", new User());
24   - }
  11 + @RequestMapping(value = "/login", method = RequestMethod.GET)
  12 + public ModelAndView login(String error, String logout) {
25 13  
26   - @RequestMapping(method = RequestMethod.POST)
27   - public String postLoginCheck(User user, BindingResult result) {
  14 + ModelAndView modelAndView = new ModelAndView("login");
28 15  
29   - User userFromRepository = userRepository.findByUsername(user.getUsername());
30   -
31   - if (userFromRepository == null) {
32   - result.rejectValue("username","login.form.invalid");
33   - return "login";
  16 + if (error != null) {
  17 + modelAndView.addObject("error", "Your username and password is invalid.");
34 18 }
35 19  
36   - if (!userFromRepository.getPassword().equals(user.getPassword())) {
37   - result.rejectValue("username","login.form.invalid");
38   - return "login";
  20 + if (logout != null) {
  21 + modelAndView.addObject("message", "You have been logged out successfully.");
39 22 }
40 23  
41   - userSession.setUsername(userFromRepository.getUsername());
42   -
43   - return "redirect:/";
44   - }
45   -
46   - public void setUserRepository(UserRepository userRepository) {
47   - this.userRepository = userRepository;
48   - }
49   -
50   - public void setUserSession(UserSession userSession) {
51   - this.userSession = userSession;
  24 + return modelAndView;
52 25 }
53   -}
54 26 \ No newline at end of file
  27 +}
... ...
src/main/java/fr/plil/sio/web/mvc/LogoutController.java deleted
... ... @@ -1,23 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import javax.annotation.Resource;
4   -import org.springframework.stereotype.Controller;
5   -import org.springframework.web.bind.annotation.RequestMapping;
6   -import org.springframework.web.bind.annotation.RequestMethod;
7   -
8   -@Controller
9   -public class LogoutController {
10   -
11   - @Resource
12   - private UserSession userSession;
13   -
14   - @RequestMapping(value = {"/logout"}, method = RequestMethod.GET)
15   - public String getLogout() {
16   - userSession.setUsername(null);
17   - return "redirect:/";
18   - }
19   -
20   - public void setUserSession(UserSession userSession) {
21   - this.userSession = userSession;
22   - }
23   -}
src/main/java/fr/plil/sio/web/mvc/NewUserController.java
1 1 package fr.plil.sio.web.mvc;
2 2  
  3 +import org.springframework.security.access.prepost.PreAuthorize;
3 4 import org.springframework.stereotype.Controller;
4 5 import org.springframework.validation.BindingResult;
5   -import org.springframework.web.bind.annotation.ModelAttribute;
6 6 import org.springframework.web.bind.annotation.RequestMapping;
7 7 import org.springframework.web.bind.annotation.RequestMethod;
8 8 import org.springframework.web.servlet.ModelAndView;
9 9  
10 10 import javax.annotation.Resource;
  11 +import javax.validation.Valid;
11 12  
12 13 @Controller
  14 +@RequestMapping(value = {"/newUser"})
13 15 public class NewUserController {
14 16  
15 17 @Resource
16   - private UserRepository userRepository;
17   -
18   - @Resource
19 18 private UserService userService;
20 19  
21   - @Resource
22   - private UserSession userSession;
23   -
24   - @Resource
25   - private UserFormValidator userFormValidator;
26   -
27   - @RequestMapping(value = {"/newUser"}, method = RequestMethod.GET)
  20 + @RequestMapping(method = RequestMethod.GET)
28 21 public ModelAndView getNewUserForm() {
29   - return new ModelAndView("newUser", "user", new User());
  22 + return new ModelAndView("newUser", "userForm", new UserForm());
30 23 }
31 24  
32   - @RequestMapping(value = {"/newUser"}, method = RequestMethod.POST)
33   - public String postNewUser(@ModelAttribute("userForm") UserForm user,
34   - BindingResult result) {
35   -
36   - if (!userSession.getUsername().equals("admin")) {
37   - result.rejectValue("username", "new.user.only.admin");
38   - }
  25 + @PreAuthorize("hasRole('ROLE_ADMIN')")
  26 + @RequestMapping(method = RequestMethod.POST)
  27 + public String postNewUser(@Valid UserForm userForm, BindingResult result) {
39 28  
40   - userFormValidator.validate(user, result);
41   -
42   - boolean present = (userRepository.findByUsername(user.getUsername()) != null);
  29 + boolean present = (userService.findByUsername(userForm.getUsername()) != null);
43 30  
44 31 if (present) {
45 32 result.rejectValue("username", "new.user.form.present");
... ... @@ -49,23 +36,11 @@ public class NewUserController {
49 36 return "newUser";
50 37 }
51 38  
52   - userService.createUser(user.getUsername(), user.getPassword());
  39 + userService.createUser(userForm.getUsername(), userForm.getPassword());
53 40  
54 41 return "redirect:/";
55 42 }
56 43  
57   - public void setUserRepository(UserRepository userRepository) {
58   - this.userRepository = userRepository;
59   - }
60   -
61   - public void setUserSession(UserSession userSession) {
62   - this.userSession = userSession;
63   - }
64   -
65   - public void setUserFormValidator(UserFormValidator userFormValidator) {
66   - this.userFormValidator = userFormValidator;
67   - }
68   -
69 44 public void setUserService(UserService userService) {
70 45 this.userService = userService;
71 46 }
... ...
src/main/java/fr/plil/sio/web/mvc/Role.java 0 โ†’ 100644
... ... @@ -0,0 +1,56 @@
  1 +package fr.plil.sio.web.mvc;
  2 +
  3 +import org.springframework.security.core.GrantedAuthority;
  4 +
  5 +import javax.persistence.*;
  6 +import java.util.Set;
  7 +import java.util.TreeSet;
  8 +
  9 +@Entity
  10 +@Table(name = "ROLE_T")
  11 +public class Role implements GrantedAuthority {
  12 +
  13 + @Id
  14 + @Column(name = "ROLE_ID")
  15 + @GeneratedValue(strategy = GenerationType.AUTO)
  16 + private Long id;
  17 +
  18 + @Column(name = "NAME_F")
  19 + private String name;
  20 +
  21 + @ManyToMany
  22 + @JoinTable(
  23 + name = "USER_ROLE_T",
  24 + joinColumns = @JoinColumn(name = "ROLE_ID", referencedColumnName = "ROLE_ID"),
  25 + inverseJoinColumns = @JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID"))
  26 + private Set<User> users = new TreeSet<>();
  27 +
  28 + public Long getId() {
  29 + return id;
  30 + }
  31 +
  32 + public void setId(Long id) {
  33 + this.id = id;
  34 + }
  35 +
  36 + public String getName() {
  37 + return name;
  38 + }
  39 +
  40 + public void setName(String name) {
  41 + this.name = name;
  42 + }
  43 +
  44 + public Set<User> getUsers() {
  45 + return users;
  46 + }
  47 +
  48 + public void setUsers(Set<User> users) {
  49 + this.users = users;
  50 + }
  51 +
  52 + @Override
  53 + public String getAuthority() {
  54 + return name;
  55 + }
  56 +}
... ...
src/main/java/fr/plil/sio/web/mvc/RoleRepository.java 0 โ†’ 100644
... ... @@ -0,0 +1,8 @@
  1 +package fr.plil.sio.web.mvc;
  2 +
  3 +import org.springframework.data.jpa.repository.JpaRepository;
  4 +
  5 +public interface RoleRepository extends JpaRepository<Role, Long> {
  6 +
  7 + Role findByName(String name);
  8 +}
... ...
src/main/java/fr/plil/sio/web/mvc/User.java
1 1 package fr.plil.sio.web.mvc;
2 2  
3 3  
  4 +import org.springframework.security.core.GrantedAuthority;
  5 +import org.springframework.security.core.userdetails.UserDetails;
  6 +
4 7 import javax.persistence.*;
  8 +import java.util.Collection;
  9 +import java.util.Set;
  10 +import java.util.TreeSet;
5 11  
6 12 @Entity
7   -public class User {
  13 +@Table(name = "USER_T")
  14 +public class User implements UserDetails {
8 15  
9 16 @Id
  17 + @Column(name = "USER_ID")
10 18 @GeneratedValue(strategy = GenerationType.AUTO)
11 19 private Long id;
12 20  
13   - @Column
  21 + @Column(name = "USERNAME_F")
14 22 private String username;
15 23  
16   - @Column
  24 + @Column(name = "PASSWORD_F")
17 25 private String password;
18 26  
19   - public User() {
  27 + @ManyToMany(mappedBy = "users", fetch = FetchType.EAGER)
  28 + private Set<Role> roles = new TreeSet<>();
  29 +
  30 + public Set<Role> getRoles() {
  31 + return roles;
20 32 }
21 33  
22   - public User(String username, String password) {
23   - this.username = username;
24   - this.password = password;
  34 + public void setRoles(Set<Role> roles) {
  35 + this.roles = roles;
  36 + }
  37 +
  38 +
  39 + @Override
  40 + public Collection<? extends GrantedAuthority> getAuthorities() {
  41 + return roles;
25 42 }
26 43  
27 44 public String getUsername() {
... ... @@ -32,6 +49,26 @@ public class User {
32 49 this.username = username;
33 50 }
34 51  
  52 + @Override
  53 + public boolean isAccountNonExpired() {
  54 + return true;
  55 + }
  56 +
  57 + @Override
  58 + public boolean isAccountNonLocked() {
  59 + return true;
  60 + }
  61 +
  62 + @Override
  63 + public boolean isCredentialsNonExpired() {
  64 + return true;
  65 + }
  66 +
  67 + @Override
  68 + public boolean isEnabled() {
  69 + return true;
  70 + }
  71 +
35 72 public String getPassword() {
36 73 return password;
37 74 }
... ...
src/main/java/fr/plil/sio/web/mvc/UserDetailsServiceImpl.java 0 โ†’ 100644
... ... @@ -0,0 +1,26 @@
  1 +package fr.plil.sio.web.mvc;
  2 +
  3 +import org.springframework.security.core.userdetails.UserDetails;
  4 +import org.springframework.security.core.userdetails.UserDetailsService;
  5 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  6 +import org.springframework.stereotype.Service;
  7 +
  8 +import javax.annotation.Resource;
  9 +
  10 +@Service
  11 +public class UserDetailsServiceImpl implements UserDetailsService {
  12 +
  13 + @Resource
  14 + private UserService userService;
  15 +
  16 + @Override
  17 + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  18 + User user = userService.findByUsername(username);
  19 +
  20 + if (user == null) {
  21 + throw new UsernameNotFoundException("cannot found user " + username);
  22 + }
  23 +
  24 + return user;
  25 + }
  26 +}
0 27 \ No newline at end of file
... ...
src/main/java/fr/plil/sio/web/mvc/UserForm.java
1 1 package fr.plil.sio.web.mvc;
2 2  
3   -import javax.validation.constraints.Max;
4   -import javax.validation.constraints.Min;
5 3 import javax.validation.constraints.NotNull;
  4 +import javax.validation.constraints.Size;
6 5  
7 6 public class UserForm {
8 7  
9   - @Min(3)
10   - @Max(16)
  8 + @NotNull
  9 + @Size(min = 3, max = 16)
11 10 private String username;
12 11  
13 12 @NotNull
  13 + @Size(min = 4)
14 14 private String password;
15 15  
16 16 public String getUsername() {
... ...
src/main/java/fr/plil/sio/web/mvc/UserFormValidator.java deleted
... ... @@ -1,41 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import org.springframework.stereotype.Component;
4   -import org.springframework.validation.Errors;
5   -import org.springframework.validation.Validator;
6   -
7   -@Component
8   -public class UserFormValidator implements Validator {
9   -
10   - @Override
11   - public boolean supports(Class<?> clazz) {
12   - return UserForm.class.equals(clazz);
13   - }
14   -
15   - private void checkUsername(String username, Errors errors) {
16   -
17   - }
18   -
19   - private void checkPassword(String password, Errors errors) {
20   - boolean hasUppercase = !password.equals(password.toLowerCase());
21   - boolean hasLowercase = !password.equals(password.toUpperCase());
22   - boolean hasSpecial = !password.matches("[A-Za-z0-9 ]*");
23   -
24   - if (!hasUppercase) {
25   - errors.rejectValue("password", "validator.user.form.must.contains.uppercase");
26   - }
27   - if (!hasLowercase) {
28   - errors.rejectValue("password", "validator.user.form.must.contains.lowercase");
29   - }
30   - if (!hasSpecial) {
31   - errors.rejectValue("password", "validator.user.form.must.contains.special.char");
32   - }
33   - }
34   -
35   - @Override
36   - public void validate(Object target, Errors errors) {
37   - UserForm user = (UserForm) target;
38   - checkUsername(user.getUsername(), errors);
39   - checkPassword(user.getPassword(), errors);
40   - }
41   -}
42 0 \ No newline at end of file
src/main/java/fr/plil/sio/web/mvc/UserService.java
... ... @@ -3,4 +3,6 @@ package fr.plil.sio.web.mvc;
3 3 public interface UserService {
4 4  
5 5 User createUser(String username, String password);
  6 +
  7 + User findByUsername(String username);
6 8 }
... ...
src/main/java/fr/plil/sio/web/mvc/UserServiceImpl.java
1 1 package fr.plil.sio.web.mvc;
2 2  
  3 +import org.springframework.security.crypto.password.PasswordEncoder;
3 4 import org.springframework.stereotype.Service;
4 5 import org.springframework.transaction.annotation.Transactional;
5 6  
6 7 import javax.annotation.Resource;
  8 +import java.util.HashSet;
  9 +import java.util.Set;
7 10  
8 11 @Service("userService")
9 12 public class UserServiceImpl implements UserService {
... ... @@ -11,13 +14,27 @@ public class UserServiceImpl implements UserService {
11 14 @Resource
12 15 private UserRepository userRepository;
13 16  
  17 + @Resource
  18 + private RoleRepository roleRepository;
  19 +
  20 + @Resource
  21 + private PasswordEncoder passwordEncoder;
  22 +
14 23 @Override
15 24 @Transactional
16 25 public User createUser(String username, String password) {
17 26 User user = new User();
18 27 user.setUsername(username);
19   - user.setPassword(password);
  28 + user.setPassword(passwordEncoder.encode(password));
  29 + Set<Role> roles = new HashSet<>();
  30 + roles.add(roleRepository.findByName("ROLE_USER"));
  31 + user.setRoles(roles);
20 32 userRepository.save(user);
21 33 return user;
22 34 }
  35 +
  36 + @Override
  37 + public User findByUsername(String username) {
  38 + return userRepository.findByUsername(username);
  39 + }
23 40 }
... ...
src/main/java/fr/plil/sio/web/mvc/UserSession.java deleted
... ... @@ -1,16 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import java.io.Serializable;
4   -
5   -public class UserSession implements Serializable {
6   -
7   - private String username;
8   -
9   - public String getUsername() {
10   - return username;
11   - }
12   -
13   - public void setUsername(String username) {
14   - this.username = username;
15   - }
16   -}
src/main/java/fr/plil/sio/web/mvc/ViewUsersController.java
... ... @@ -14,19 +14,11 @@ public class ViewUsersController {
14 14 @Resource
15 15 private UserRepository userRepository;
16 16  
17   - @Resource
18   - private UserSession userSession;
19   -
20 17 @ModelAttribute("users")
21 18 public List<User> populateUsers() {
22 19 return userRepository.findAll();
23 20 }
24 21  
25   - @ModelAttribute("userSession")
26   - public UserSession populateUser() {
27   - return userSession;
28   - }
29   -
30 22 @RequestMapping(value={"/"},method=RequestMethod.GET)
31 23 public String getViewUsers() {
32 24 return "viewUsers";
... ... @@ -35,8 +27,4 @@ public class ViewUsersController {
35 27 public void setUserRepository(UserRepository userRepository) {
36 28 this.userRepository = userRepository;
37 29 }
38   -
39   - public void setUserSession(UserSession userSession) {
40   - this.userSession = userSession;
41   - }
42 30 }
... ...
src/main/resources/application.properties
... ... @@ -2,6 +2,6 @@ logging.level.fr.plil.sio.web.mvc=DEBUG
2 2 logging.level.org.hibernate=INFO
3 3  
4 4 spring.jpa.hibernate.ddl-auto=create-drop
5   -
6   -spring.view.prefix=/WEB-INF/views/
7   -spring.view.suffix=.jsp
  5 +spring.mvc.view.prefix=/WEB-INF/pages/
  6 +spring.mvc.view.suffix=.jsp
  7 +security.enable-csrf=false
8 8 \ No newline at end of file
... ...
src/main/resources/import.sql
1   -INSERT INTO USER (username,password) VALUES ('admin','admin')
2 1 \ No newline at end of file
  2 +INSERT INTO USER_T (USERNAME_F, PASSWORD_F)
  3 +VALUES ('admin', '$2a$04$/87gxfQlNqMNRvI/ILyZ/.F8Bk2/t2RuWoZXE1upQHeUglbjTYIIa');
  4 +INSERT INTO ROLE_T (NAME_F) VALUES ('ROLE_ADMIN');
  5 +INSERT INTO ROLE_T (NAME_F) VALUES ('ROLE_USER');
  6 +INSERT INTO USER_ROLE_T (USER_ID, ROLE_ID) VALUES ((SELECT USER_ID
  7 + FROM USER_T
  8 + WHERE USERNAME_F = 'admin'), (SELECT ROLE_ID
  9 + FROM ROLE_T
  10 + WHERE NAME_F = 'ROLE_ADMIN'));
3 11 \ No newline at end of file
... ...
src/main/resources/messages.properties
1 1 domain.user.username=Username
2 2 domain.user.password=Password
3 3  
4   -validator.user.username.minimal.size=Username must be at least 3 characters
5   -validator.user.password.minimal.size=Password must be at least 3 characters
6   -
7   -login.page.title=Login Page
8   -login.main.header=Please login...
9   -login.form.submit=login
10   -login.form.invalid=Invalid username and/or password
11   -
12 4 view.users.page.title=User List
13 5 view.users.main.header=List of users
14 6 view.users.greetings=Hello
... ... @@ -17,5 +9,4 @@ view.users.main.logout=Logout
17 9 new.user.page.title=New user
18 10 new.user.main.header=Add a new user
19 11 new.user.form.submit=Add the user
20   -new.user.only.admin=Only administrator user can do it
21 12 new.user.form.present=user already present
22 13 \ No newline at end of file
... ...
src/main/webapp/WEB-INF/pages/login.jsp 0 โ†’ 100644
... ... @@ -0,0 +1,34 @@
  1 +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  2 +<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3 +<html>
  4 +<head>
  5 + <title>Title</title>
  6 +</head>
  7 +<body>
  8 +<c:url value="/login" var="loginUrl"/>
  9 +<form action="${loginUrl}" method="post">
  10 + <c:if test="${param.error != null}">
  11 + <p>
  12 + Invalid username and password.
  13 + </p>
  14 + </c:if>
  15 + <c:if test="${param.logout != null}">
  16 + <p>
  17 + You have been logged out.
  18 + </p>
  19 + </c:if>
  20 + <p>
  21 + <label for="username">Username</label>
  22 + <input type="text" id="username" name="username"/>
  23 + </p>
  24 + <p>
  25 + <label for="password">Password</label>
  26 + <input type="password" id="password" name="password"/>
  27 + </p>
  28 + <input type="hidden"
  29 + name="${_csrf.parameterName}"
  30 + value="${_csrf.token}"/>
  31 + <button type="submit" class="btn">Log in</button>
  32 +</form>
  33 +</body>
  34 +</html>
... ...
src/main/webapp/WEB-INF/views/newUser.jsp renamed to src/main/webapp/WEB-INF/pages/newUser.jsp
... ... @@ -12,7 +12,7 @@
12 12 </head>
13 13 <body>
14 14 <h1><spring:message code="new.user.main.header"/></h1>
15   - <form:form commandName="user" method="POST">
  15 + <form:form commandName="userForm" method="POST">
16 16 <table>
17 17 <tr>
18 18 <td><form:errors path="username"/></td>
... ...
src/main/webapp/WEB-INF/views/viewUsers.jsp renamed to src/main/webapp/WEB-INF/pages/viewUsers.jsp
... ... @@ -32,7 +32,7 @@
32 32  
33 33 <ul>
34 34 <li><a href="newUser"><spring:message code="new.user.main.header"/></a></li>
35   - <li><a href="logout"><spring:message code="view.users.main.logout"/></a></li>
  35 + <li><a href="login?logout"><spring:message code="view.users.main.logout"/></a></li>
36 36 </ul>
37 37  
38 38 </body>
... ...
src/main/webapp/WEB-INF/views/login.jsp deleted
... ... @@ -1,33 +0,0 @@
1   -<%@ page contentType="text/html" pageEncoding="UTF-8" %>
2   -<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
3   -<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
4   -
5   -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
6   - "http://www.w3.org/TR/html4/strict.dtd">
7   -
8   -<html>
9   - <head>
10   - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
11   - <title><spring:message code="login.page.title"/></title>
12   - </head>
13   - <body>
14   - <h1><spring:message code="login.main.header"/></h1>
15   - <form:form commandName="user" method="POST">
16   - <table id="login" class="box">
17   - <tr>
18   - <td><form:errors path="*"/></td>
19   - </tr>
20   - <tr>
21   - <td><spring:message code="domain.user.username"/></td>
22   - <td><form:input path="username"/></td>
23   - </tr>
24   - <tr>
25   - <td><spring:message code="domain.user.password"/></td>
26   - <td><form:password path="password"/></td></tr>
27   - <tr>
28   - <td><input type="submit" value="<spring:message code="login.form.submit"/>"/></td>
29   - </tr>
30   - </table>
31   - </form:form>
32   - </body>
33   -</html>
34 0 \ No newline at end of file
src/test/java/fr/plil/sio/web/mvc/CheckUserInterceptorTest.java deleted
... ... @@ -1,45 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import java.io.IOException;
4   -import static org.junit.Assert.*;
5   -import org.junit.Before;
6   -import org.junit.Test;
7   -import org.springframework.mock.web.MockHttpServletRequest;
8   -import org.springframework.mock.web.MockHttpServletResponse;
9   -
10   -public class CheckUserInterceptorTest {
11   -
12   - private CheckUserInterceptor interceptor;
13   - private UserSession userSession;
14   - private MockHttpServletRequest request;
15   - private MockHttpServletResponse response;
16   -
17   - @Before
18   - public void createInstances() {
19   - interceptor = new CheckUserInterceptor();
20   - userSession = new UserSession();
21   - interceptor.setUserSession(userSession);
22   - request = new MockHttpServletRequest();
23   - response = new MockHttpServletResponse();
24   - }
25   -
26   - @Test
27   - public void checkPreHandleServletPathIsLogin() throws IOException {
28   - request.setServletPath("/login");
29   - assertTrue(interceptor.preHandle(request, response, null));
30   - }
31   -
32   - @Test
33   - public void checkPreHandleUsernameInSession() throws IOException {
34   - userSession.setUsername("admin");
35   - request.setServletPath("/blabla");
36   - assertTrue(interceptor.preHandle(request, response, null));
37   - }
38   -
39   - @Test
40   - public void checkPreHandleUsernameNotInSession() throws IOException {
41   - request.setServletPath("/blabla");
42   - assertFalse(interceptor.preHandle(request, response, null));
43   - assertEquals(response.getRedirectedUrl(),"login");
44   - }
45   -}
src/test/java/fr/plil/sio/web/mvc/LoginControllerTest.java deleted
... ... @@ -1,59 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import org.junit.Before;
4   -import org.junit.Test;
5   -import org.springframework.validation.BeanPropertyBindingResult;
6   -import org.springframework.validation.BindingResult;
7   -import org.springframework.web.servlet.ModelAndView;
8   -
9   -import static org.junit.Assert.*;
10   -import static org.mockito.Mockito.mock;
11   -import static org.mockito.Mockito.when;
12   -
13   -public class LoginControllerTest {
14   -
15   - private LoginController loginController;
16   - private BindingResult results;
17   - private User user;
18   - private UserRepository userRepository;
19   - private UserSession userSession;
20   -
21   - @Before
22   - public void createInstances() {
23   - loginController = new LoginController();
24   - user = new User();
25   - results = new BeanPropertyBindingResult(user, "user");
26   - userRepository = mock(UserRepository.class);
27   - when(userRepository.findByUsername("admin")).thenReturn(new User("admin", "admin"));
28   - loginController.setUserRepository(userRepository);
29   - userSession = new UserSession();
30   - loginController.setUserSession(userSession);
31   - }
32   -
33   - @Test
34   - public void testGetLoginForm() {
35   - ModelAndView mav = loginController.getLoginForm();
36   - assertEquals("login", mav.getViewName());
37   - assertEquals(1, mav.getModelMap().size());
38   - assertTrue(mav.getModel().containsKey("user"));
39   - assertTrue(mav.getModel().get("user") instanceof User);
40   - }
41   -
42   - @Test
43   - public void testPostLoginCheckSucceed() {
44   - user.setUsername("admin");
45   - user.setPassword("admin");
46   - String view = loginController.postLoginCheck(user, results);
47   - assertFalse(results.hasErrors());
48   - assertEquals("redirect:/",view);
49   - }
50   -
51   - @Test
52   - public void testPostLoginCheckFailed() {
53   - user.setUsername("abc");
54   - user.setPassword("abc");
55   - String view = loginController.postLoginCheck(user, results);
56   - assertTrue(results.hasErrors());
57   - assertEquals("login",view);
58   - }
59   -}
src/test/java/fr/plil/sio/web/mvc/LogoutControllerTest.java deleted
... ... @@ -1,18 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import static org.junit.Assert.*;
4   -import org.junit.Test;
5   -
6   -public class LogoutControllerTest {
7   -
8   - @Test
9   - public void testGetLogout() {
10   - LogoutController logoutController = new LogoutController();
11   - UserSession userSession = new UserSession();
12   - userSession.setUsername("blabla");
13   - logoutController.setUserSession(userSession);
14   - String view = logoutController.getLogout();
15   - assertNull(userSession.getUsername());
16   - assertEquals("redirect:/",view);
17   - }
18   -}
src/test/java/fr/plil/sio/web/mvc/NewUserControllerTest.java
... ... @@ -13,28 +13,20 @@ public class NewUserControllerTest {
13 13  
14 14 private NewUserController newUserController;
15 15 private BindingResult results;
16   - private UserForm user;
17   - private UserRepository userRepository;
18   - private UserSession userSession;
19   - private UserFormValidator userFormValidator;
  16 + private UserForm userForm;
20 17 private UserService userService;
21 18  
22 19 @Before
23 20 public void createInstances() {
24 21 newUserController = new NewUserController();
25   - user = new UserForm();
26   - results = new BeanPropertyBindingResult(user, "user");
27   - userRepository = mock(UserRepository.class);
28   - User user = new User("admin", "password");
29   - when(userRepository.findByUsername("admin")).thenReturn(user);
30   - newUserController.setUserRepository(userRepository);
  22 + userForm = new UserForm();
  23 + results = new BeanPropertyBindingResult(userForm, "user");
  24 + userService = mock(UserService.class);
  25 + User user = new User();
  26 + when(userService.findByUsername("admin")).thenReturn(user);
  27 + newUserController.setUserService(userService);
31 28 userService = mock(UserService.class);
32 29 newUserController.setUserService(userService);
33   - userSession = new UserSession();
34   - userSession.setUsername("admin");
35   - newUserController.setUserSession(userSession);
36   - userFormValidator = new UserFormValidator();
37   - newUserController.setUserFormValidator(userFormValidator);
38 30 }
39 31  
40 32 @Test
... ... @@ -48,9 +40,9 @@ public class NewUserControllerTest {
48 40  
49 41 @Test
50 42 public void testPostNewUserSucceed() {
51   - user.setUsername("abc");
52   - user.setPassword("abcD#");
53   - String view = newUserController.postNewUser(user, results);
  43 + userForm.setUsername("abc");
  44 + userForm.setPassword("abcD#");
  45 + String view = newUserController.postNewUser(userForm, results);
54 46 assertFalse(results.hasErrors());
55 47 assertEquals("redirect:/", view);
56 48 verify(userService).createUser("abc", "abcD#");
... ... @@ -58,28 +50,27 @@ public class NewUserControllerTest {
58 50  
59 51 @Test
60 52 public void testPostNewUserFailedNotAdmin() {
61   - user.setUsername("abc");
62   - user.setPassword("abcD#");
63   - userSession.setUsername("blabla");
64   - String view = newUserController.postNewUser(user, results);
  53 + userForm.setUsername("abc");
  54 + userForm.setPassword("abcD#");
  55 + String view = newUserController.postNewUser(userForm, results);
65 56 assertTrue(results.hasErrors());
66 57 assertEquals("newUser",view);
67 58 }
68 59  
69 60 @Test
70 61 public void testPostNewUserFailedValidate() {
71   - user.setUsername("a");
72   - user.setPassword("abc");
73   - String view = newUserController.postNewUser(user, results);
  62 + userForm.setUsername("a");
  63 + userForm.setPassword("abc");
  64 + String view = newUserController.postNewUser(userForm, results);
74 65 assertTrue(results.hasErrors());
75 66 assertEquals("newUser",view);
76 67 }
77 68  
78 69 @Test
79 70 public void testPostNewUserFailedAlreadyPresent() {
80   - user.setUsername("admin");
81   - user.setPassword("blabla");
82   - String view = newUserController.postNewUser(user, results);
  71 + userForm.setUsername("admin");
  72 + userForm.setPassword("blabla");
  73 + String view = newUserController.postNewUser(userForm, results);
83 74 assertTrue(results.hasErrors());
84 75 assertEquals("newUser",view);
85 76 }
... ...
src/test/java/fr/plil/sio/web/mvc/UserFormValidatorTest.java deleted
... ... @@ -1,37 +0,0 @@
1   -package fr.plil.sio.web.mvc;
2   -
3   -import org.junit.Before;
4   -import org.junit.Test;
5   -import org.springframework.validation.BeanPropertyBindingResult;
6   -import org.springframework.validation.Errors;
7   -
8   -import static org.junit.Assert.assertFalse;
9   -import static org.junit.Assert.assertTrue;
10   -
11   -public class UserFormValidatorTest {
12   -
13   - private UserForm user;
14   - private UserFormValidator validator;
15   - private Errors results;
16   -
17   - @Before
18   - public void createInstances() {
19   - validator = new UserFormValidator();
20   - user = new UserForm();
21   - user.setUsername("abc");
22   - user.setPassword("abc#A");
23   - results = new BeanPropertyBindingResult(user, "user");
24   - }
25   -
26   - @Test
27   - public void testSupports() {
28   - assertTrue(validator.supports(UserForm.class));
29   - }
30   -
31   - @Test
32   - public void testValidateCorrect() {
33   - validator.validate(user,results);
34   - assertFalse(results.hasErrors());
35   - }
36   -
37   -}
src/test/java/fr/plil/sio/web/mvc/ViewUsersControllerTest.java
... ... @@ -24,7 +24,6 @@ public class ViewUsersControllerTest {
24 24  
25 25 private ViewUsersController viewUsersController;
26 26 private UserRepository userRepository;
27   - private UserSession userSession;
28 27  
29 28 private MockMvc mockMvc;
30 29  
... ... @@ -34,12 +33,12 @@ public class ViewUsersControllerTest {
34 33 mockMvc = MockMvcBuilders.standaloneSetup(viewUsersController).build();
35 34 userRepository = mock(UserRepository.class);
36 35 List<User> users = new LinkedList<>();
37   - users.add(new User("admin", "password"));
  36 + User testUser = new User();
  37 + testUser.setPassword("admin");
  38 + testUser.setUsername("password");
  39 + users.add(testUser);
38 40 when(userRepository.findAll()).thenReturn(users);
39 41 viewUsersController.setUserRepository(userRepository);
40   - userSession = new UserSession();
41   - userSession.setUsername("admin");
42   - viewUsersController.setUserSession(userSession);
43 42 }
44 43  
45 44 @Test
... ... @@ -47,7 +46,6 @@ public class ViewUsersControllerTest {
47 46 mockMvc.perform(get("/"))
48 47 .andExpect(status().isOk())
49 48 .andExpect(view().name("viewUsers"))
50   - .andExpect(model().attributeExists("users"))
51   - .andExpect(model().attributeExists("userSession"));
  49 + .andExpect(model().attributeExists("users"));
52 50 }
53 51 }
... ...