From 9eebb2bfff2655e4cf3857ef67b2977cd61cbd8e Mon Sep 17 00:00:00 2001 From: L_DelOff <51275636+LDelOff@users.noreply.github.com> Date: Wed, 1 Mar 2023 23:46:16 +0300 Subject: [PATCH] =?UTF-8?q?Security=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 64 +++++++++++++++++++ src/main/java/ru/ldeloff/Main.java | 7 -- .../java/ru/ldeloff/hedgehogcloud/Main.java | 11 ++++ .../AuthenticationSuccessUserHandler.java | 25 ++++++++ .../hedgehogcloud/config/MvcConfig.java | 13 ++++ .../config/WebSecurityConfig.java | 61 ++++++++++++++++++ .../controller/LoginController.java | 13 ++++ .../hedgehogcloud/entity/RoleEntity.java | 31 +++++++++ .../hedgehogcloud/entity/UserEntity.java | 63 ++++++++++++++++++ .../repository/RoleRepository.java | 7 ++ .../repository/UserRepository.java | 8 +++ .../hedgehogcloud/service/UserService.java | 38 +++++++++++ src/main/resources/application.yml | 14 ++++ src/main/resources/templates/login.html | 26 ++++++++ 14 files changed, 374 insertions(+), 7 deletions(-) delete mode 100644 src/main/java/ru/ldeloff/Main.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/Main.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/config/AuthenticationSuccessUserHandler.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/config/MvcConfig.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/config/WebSecurityConfig.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/controller/LoginController.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/entity/RoleEntity.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/entity/UserEntity.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/repository/RoleRepository.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/repository/UserRepository.java create mode 100644 src/main/java/ru/ldeloff/hedgehogcloud/service/UserService.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/templates/login.html diff --git a/pom.xml b/pom.xml index 7a4a000..4c7f6ec 100644 --- a/pom.xml +++ b/pom.xml @@ -8,9 +8,73 @@ HedgeHogCloud 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.6.2 + + 17 17 + 17 + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-test + test + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.projectlombok + lombok + 1.18.26 + provided + + + + org.liquibase + liquibase-core + 4.19.0 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${project.parent.version} + + + + \ No newline at end of file diff --git a/src/main/java/ru/ldeloff/Main.java b/src/main/java/ru/ldeloff/Main.java deleted file mode 100644 index 7620479..0000000 --- a/src/main/java/ru/ldeloff/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.ldeloff; - -public class Main { - public static void main(String[] args) { - System.out.println("Hello world!"); - } -} \ No newline at end of file diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/Main.java b/src/main/java/ru/ldeloff/hedgehogcloud/Main.java new file mode 100644 index 0000000..682f8e1 --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/Main.java @@ -0,0 +1,11 @@ +package ru.ldeloff.hedgehogcloud; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class,args); + } +} \ No newline at end of file diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/config/AuthenticationSuccessUserHandler.java b/src/main/java/ru/ldeloff/hedgehogcloud/config/AuthenticationSuccessUserHandler.java new file mode 100644 index 0000000..74e28cd --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/config/AuthenticationSuccessUserHandler.java @@ -0,0 +1,25 @@ +package ru.ldeloff.hedgehogcloud.config; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Set; + +@Component +public class AuthenticationSuccessUserHandler implements AuthenticationSuccessHandler { + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + Set roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities()); + if (roles.contains("ROLE_ADMIN")) { + response.sendRedirect("/admin"); + } else { + response.sendRedirect("/user"); + } + } +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/config/MvcConfig.java b/src/main/java/ru/ldeloff/hedgehogcloud/config/MvcConfig.java new file mode 100644 index 0000000..8160a3c --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/config/MvcConfig.java @@ -0,0 +1,13 @@ +package ru.ldeloff.hedgehogcloud.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class MvcConfig implements WebMvcConfigurer { + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/login").setViewName("login"); + } +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/config/WebSecurityConfig.java b/src/main/java/ru/ldeloff/hedgehogcloud/config/WebSecurityConfig.java new file mode 100644 index 0000000..fbfe448 --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/config/WebSecurityConfig.java @@ -0,0 +1,61 @@ +package ru.ldeloff.hedgehogcloud.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import ru.ldeloff.hedgehogcloud.service.UserService; + + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + UserService userService; + AuthenticationSuccessUserHandler authenticationSuccessUserHandler; + + public WebSecurityConfig(UserService userService, AuthenticationSuccessUserHandler authenticationSuccessUserHandler) { + this.userService = userService; + this.authenticationSuccessUserHandler = authenticationSuccessUserHandler; + } + + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.formLogin() + // указываем страницу с формой логина + .loginPage("/login") + //указываем логику обработки при логине + .successHandler(authenticationSuccessUserHandler) + // указываем action с формы логина + .loginProcessingUrl("/login") + // указываем параметры логина и пароля с формы логина + .usernameParameter("j_username") + .passwordParameter("j_password") + // даем доступ к форме логина всем + .permitAll(); + http + // делаем страницу регистрации недоступной для авторизированных пользователей + .authorizeRequests() + //страницы аутентификации доступна всем + .antMatchers("/login").anonymous() + .antMatchers("/").authenticated() + // защищенные URL + .antMatchers("/admin/**").access("hasAnyRole('ROLE_ADMIN')") + .antMatchers("/user").permitAll() + .and().formLogin(); + } + + @Autowired + protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userService).passwordEncoder(NoOpPasswordEncoder.getInstance()); + } +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/controller/LoginController.java b/src/main/java/ru/ldeloff/hedgehogcloud/controller/LoginController.java new file mode 100644 index 0000000..ba5629c --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/controller/LoginController.java @@ -0,0 +1,13 @@ +package ru.ldeloff.hedgehogcloud.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class LoginController { + + @GetMapping(value = "/login") + public String loginPage() { + return "login"; + } +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/entity/RoleEntity.java b/src/main/java/ru/ldeloff/hedgehogcloud/entity/RoleEntity.java new file mode 100644 index 0000000..da5eb44 --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/entity/RoleEntity.java @@ -0,0 +1,31 @@ +package ru.ldeloff.hedgehogcloud.entity; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.util.Set; + +@NoArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "roles") +public class RoleEntity implements GrantedAuthority { + @Id + private String id; + private String name; + @Transient + private Set users; + + @Override + public String getAuthority() { + return getName(); + } +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/entity/UserEntity.java b/src/main/java/ru/ldeloff/hedgehogcloud/entity/UserEntity.java new file mode 100644 index 0000000..94a8749 --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/entity/UserEntity.java @@ -0,0 +1,63 @@ +package ru.ldeloff.hedgehogcloud.entity; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.persistence.*; +import java.util.Collection; +import java.util.Set; + +@NoArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "users") +public class UserEntity implements UserDetails { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private String id; + private String username; + private String password; + + @ManyToMany(fetch = FetchType.EAGER) + private Set roles; + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/repository/RoleRepository.java b/src/main/java/ru/ldeloff/hedgehogcloud/repository/RoleRepository.java new file mode 100644 index 0000000..75a517f --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/repository/RoleRepository.java @@ -0,0 +1,7 @@ +package ru.ldeloff.hedgehogcloud.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ldeloff.hedgehogcloud.entity.RoleEntity; + +public interface RoleRepository extends JpaRepository { +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/repository/UserRepository.java b/src/main/java/ru/ldeloff/hedgehogcloud/repository/UserRepository.java new file mode 100644 index 0000000..4603bcf --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/repository/UserRepository.java @@ -0,0 +1,8 @@ +package ru.ldeloff.hedgehogcloud.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ldeloff.hedgehogcloud.entity.UserEntity; + +public interface UserRepository extends JpaRepository { + UserEntity findByUsername(String username); +} diff --git a/src/main/java/ru/ldeloff/hedgehogcloud/service/UserService.java b/src/main/java/ru/ldeloff/hedgehogcloud/service/UserService.java new file mode 100644 index 0000000..17654ec --- /dev/null +++ b/src/main/java/ru/ldeloff/hedgehogcloud/service/UserService.java @@ -0,0 +1,38 @@ +package ru.ldeloff.hedgehogcloud.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import ru.ldeloff.hedgehogcloud.entity.UserEntity; +import ru.ldeloff.hedgehogcloud.repository.RoleRepository; +import ru.ldeloff.hedgehogcloud.repository.UserRepository; + +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + + +@Service +public class UserService implements UserDetailsService { + UserRepository userRepository; + RoleRepository roleRepository; + + @Autowired + public UserService(UserRepository userRepository, + RoleRepository roleRepository) { + this.userRepository = userRepository; + this.roleRepository = roleRepository; + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UserEntity user = userRepository.findByUsername(username); + if (user == null) { + throw new UsernameNotFoundException("User not found"); + } + return user; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..c2e5d26 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,14 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/hedgehogcloud?verifyServerCertificate=false&useSSL=false&requireSSL=false&useLegacyDatetimeCode=false&&serverTimezone=UTC&allowPublicKeyRetrieval=true + username: root + password: 123 + liquibase: + enabled: true + change-log: classpath:db/scripts/changelog-master.xml + url: jdbc:mysql://localhost:3306/hedgehogcloud?verifyServerCertificate=false&useSSL=false&requireSSL=false&useLegacyDatetimeCode=false&&serverTimezone=UTC&allowPublicKeyRetrieval=true + user: root + password: 123 + liquibase-schema: "liquibase" + default-schema: "hedgehogcloud" diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html new file mode 100644 index 0000000..a69d21c --- /dev/null +++ b/src/main/resources/templates/login.html @@ -0,0 +1,26 @@ + + + + + + Login Page + + + +
+
+
+
+
+

Please sign in

+ + + +
+
+
+
+
+ + + \ No newline at end of file