Commit 60483f52 authored by s7_aigars_v's avatar s7_aigars_v
Browse files

Merge branch 'spring-security' into 'master'

Implemented authorization and registration

See merge request s7_spruge_k/calendar!7
parents adad28e1 3eb3e53a
File added
File added
#FileLock
#Tue Jun 11 13:24:29 EEST 2019
id=16b461154a882bdf9b529981acc46ca421ea9ffbeb0
method=file
......@@ -50,6 +50,24 @@
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -4,18 +4,18 @@ package com.example.calendar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
@EnableJpaRepositories
public class CalendarApplication {
public static void main(String[] args) {
SpringApplication.run(CalendarApplication.class, args);
System.out.println("Event test");
}
public class CalendarApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(CalendarApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(CalendarApplication.class, args);
}
}
package com.example.calendar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public AuthenticationManager customAuthenticationManager() throws Exception {
return authenticationManager();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
\ No newline at end of file
package com.example.calendar.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import com.example.calendar.models.User;
import com.example.calendar.service.SecurityService;
import com.example.calendar.service.UserService;
import com.example.calendar.validator.UserValidator;
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private SecurityService securityService;
@Autowired
private UserValidator userValidator;
@GetMapping("/registration")
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
@PostMapping("/registration")
public String registration(@ModelAttribute("userForm") User userForm, BindingResult bindingResult) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
System.out.println("error");
return "registration";
}
userService.save(userForm);
securityService.autoLogin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/welcome";
}
@GetMapping("/login")
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "login";
}///login POST controller is provided by Spring Security
@GetMapping({"/", "/welcome"})
public String welcome(Model model) {
return "welcome";
}
}
\ No newline at end of file
package com.example.calendar.models;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
\ No newline at end of file
package com.example.calendar.models;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.springframework.data.annotation.Transient;
@Entity
@Table(name = "UserTable")
public class User {
......@@ -17,6 +22,13 @@ public class User {
private String username;
@Column(name = "Password")
private String password;
@Transient
private String passwordConfirm;
@ManyToMany
private Set<Role> roles;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID_u")
......@@ -52,6 +64,35 @@ public class User {
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public User() {
super();
}
@Override
public String toString() {
......
package com.example.calendar.repo;
import org.springframework.data.repository.CrudRepository;
import com.example.calendar.models.Role;
public interface RoleRepo extends CrudRepository<Role, Integer>{
}
......@@ -7,5 +7,5 @@ import com.example.calendar.models.User;
@Repository
public interface UserRepo extends CrudRepository<User, Integer>{
User findByUsername(String username);
}
package com.example.calendar.service;
public interface SecurityService {
String findLoggedInUsername();
void autoLogin(String username, String password);
}
package com.example.calendar.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
@Service
public class SecurityServiceImpl implements SecurityService{
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(SecurityServiceImpl.class);
@Override
public String findLoggedInUsername() {
Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
if (userDetails instanceof UserDetails) {
return ((UserDetails)userDetails).getUsername();
}
return null;
}
@Override
public void autoLogin(String username, String password) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
authenticationManager.authenticate(usernamePasswordAuthenticationToken);
if (usernamePasswordAuthenticationToken.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
logger.debug(String.format("Auto login %s successfully!", username));
}
}
}
\ No newline at end of file
package com.example.calendar.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.calendar.models.Role;
import com.example.calendar.models.User;
import com.example.calendar.repo.UserRepo;
import java.util.HashSet;
import java.util.Set;
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UserRepo userRepository;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
if (user == null) throw new UsernameNotFoundException(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()){
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
}
\ No newline at end of file
package com.example.calendar.service;
import com.example.calendar.models.User;
public interface UserService {
void save(User user);
User findByUsername(String username);
}
\ No newline at end of file
package com.example.calendar.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.example.calendar.models.Role;
import com.example.calendar.models.User;
import com.example.calendar.repo.RoleRepo;
import com.example.calendar.repo.UserRepo;
import java.util.Collection;
import java.util.HashSet;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepo userRepository;
@Autowired
private RoleRepo roleRepository;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
public void save(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
user.setRoles(new HashSet<Role>((Collection<? extends Role>) roleRepository.findAll()));
userRepository.save(user);
}
@Override
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
}
\ No newline at end of file
package com.example.calendar.validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import com.example.calendar.models.User;
import com.example.calendar.service.UserService;
@Component
public class UserValidator implements Validator {
@Autowired
private UserService userService;
@Override
public boolean supports(Class<?> aClass) {
return User.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
User user = (User) o;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "NotEmpty");
if (user.getUsername().length() < 6 || user.getUsername().length() > 32) {
errors.rejectValue("username", "Size.userForm.username");
}
if (userService.findByUsername(user.getUsername()) != null) {
errors.rejectValue("username", "Duplicate.userForm.username");
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "NotEmpty");
if (user.getPassword().length() < 8 || user.getPassword().length() > 32) {
errors.rejectValue("password", "Size.userForm.password");
}
if (!user.getPasswordConfirm().equals(user.getPassword())) {
errors.rejectValue("passwordConfirm", "Diff.userForm.passwordConfirm");
}
}
}
\ No newline at end of file
spring.datasource.url=jdbc:h2:file:./db
spring.datasource.url=jdbc:h2:file:./db;mv_store=false
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=root
spring.datasource.password=parole123
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
\ No newline at end of file
spring.jpa.hibernate.ddl-auto=update
spring.messages.basename=validation
spring.mvc.view.suffix = .jsp
spring.mvc.view.prefix = /WEB-INF/classes/templates
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="spring" ref="http://www.springframework.org/tags" />
<property name="form" value="http://www.springframework.org/tags/form" />
</bean>
<!DOCTYPE html>
<html xmlns:th="www.tymeleaf.org" lang="en">
<head>
<meta charset="utf-8">
<title>Authentification</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="/resources/css/common.css" rel="stylesheet">
</head>
<body>
<div class="container">
<form action="#" method="POST" th:action="@{/login}" class="form-signin">
<h2 class="form-heading">Log in</h2>
<div class="form-group">
<div class="alert alert-danger" th:if="${message}">
<p th:text="${message}"></p>
</div>
<input name="username" type="text" class="form-control" placeholder="Username"
autofocus="true"/>
<input name="password" type="password" class="form-control" placeholder="Password"/>
<div class="alert alert-danger" th:if="${error}">
<p th:text="${error}"></p>
</div>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">Log In</button>
<h4 class="text-center"><a href="/registration">Create an account</a></h4>
</div>
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="/resources/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment