Commit 322c9502a32ebc9aeee8179c5eac890ca876211c
1 parent
88ff471f
Ad Spring security support and validation
Showing
31 changed files
with
309 additions
and
492 deletions
Show diff stats
pom.xml
... | ... | @@ -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 | } | ... | ... |
... | ... | @@ -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
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
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 | ... | ... |
... | ... | @@ -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
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 | } | ... | ... |