#11 -- Add security config

This commit is contained in:
Anton Romanov 2025-02-14 20:14:41 +04:00
parent 1f22e12dd4
commit a2ff48a165
11 changed files with 132 additions and 33 deletions

View File

@ -2,11 +2,28 @@ package ru.ulstu.fc;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.event.EventListener;
import ru.ulstu.fc.user.service.UserService;
@SpringBootApplication @SpringBootApplication
@EnableConfigurationProperties
public class FuzzyControllerApplication { public class FuzzyControllerApplication {
private final UserService userService;
public FuzzyControllerApplication(UserService userService) {
this.userService = userService;
}
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(FuzzyControllerApplication.class, args); SpringApplication.run(FuzzyControllerApplication.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
System.out.println("hello world, I have just started up");
userService.initDefaultAdmin();
}
} }

View File

@ -1,9 +1,3 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*
*/
package ru.ulstu.fc.config; package ru.ulstu.fc.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -11,12 +5,19 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration @Configuration
public class MvcConfiguration implements WebMvcConfigurer { public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login");
registry.addViewController("/loginError");
registry.addViewController("/index");
}
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {

View File

@ -0,0 +1,13 @@
package ru.ulstu.fc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class PasswordEncoderConfiguration {
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,52 @@
package ru.ulstu.fc.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import ru.ulstu.fc.user.model.UserRoleConstants;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration {
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
private final String[] permittedUrls = new String[]{
"/login", "/index",
"/public/**", "/organizers", "/webjars/**",
"/h2-console/*", "/h2-console",
"/css/**", "/js/**", "/img/**",
"/templates/**", "/webjars/**"};
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
log.debug("Security enabled");
http
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth ->
auth.requestMatchers("/").permitAll()
.requestMatchers(permittedUrls).permitAll()
.requestMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN)
.anyRequest().authenticated())
.formLogin(form ->
form.loginPage("/login")
.failureUrl("/loginError")
.permitAll())
.logout(logout ->
logout
.logoutSuccessUrl(Constants.LOGOUT_URL)
.invalidateHttpSession(false)
.clearAuthentication(true)
.deleteCookies(Constants.COOKIES_NAME)
.permitAll());
return http.build();
}
}

View File

@ -1,13 +0,0 @@
package ru.ulstu.fc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfiguration {
@Bean
public WebClient webClient(WebClient.Builder webClientBuilder) {
return webClientBuilder.build();
}
}

View File

@ -1,6 +1,7 @@
package ru.ulstu.fc.project.controller; package ru.ulstu.fc.project.controller;
import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Hidden;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
@ -9,10 +10,12 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import ru.ulstu.fc.project.model.ProjectForm; import ru.ulstu.fc.project.model.ProjectForm;
import ru.ulstu.fc.project.service.ProjectService; import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.user.model.UserRoleConstants;
@Controller @Controller
@Hidden @Hidden
@RequestMapping("project") @RequestMapping("project")
@Secured({UserRoleConstants.ADMIN})
public class ProjectController { public class ProjectController {
private final ProjectService projectService; private final ProjectService projectService;

View File

@ -1,5 +1,6 @@
package ru.ulstu.fc.project.controller; package ru.ulstu.fc.project.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -8,11 +9,13 @@ import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.fc.project.model.Project; import ru.ulstu.fc.project.model.Project;
import ru.ulstu.fc.project.model.ProjectForm; import ru.ulstu.fc.project.model.ProjectForm;
import ru.ulstu.fc.project.service.ProjectService; import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.user.model.UserRoleConstants;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("projectRest") @RequestMapping("projectRest")
@Secured({UserRoleConstants.ADMIN})
public class ProjectRestController { public class ProjectRestController {
private final ProjectService projectService; private final ProjectService projectService;

View File

@ -1,8 +1,8 @@
package ru.ulstu.fc.project.model; package ru.ulstu.fc.project.model;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import ru.ulstu.fc.core.model.BaseEntity; import ru.ulstu.fc.core.model.BaseEntity;
import ru.ulstu.fc.user.model.User; import ru.ulstu.fc.user.model.User;
@ -10,10 +10,10 @@ import java.util.Date;
@Entity @Entity
public class Project extends BaseEntity { public class Project extends BaseEntity {
@NotEmpty @NotEmpty(message = "Текст новости не может быть пустым")
private String name; private String name;
private Date createDate = new Date(); private Date createDate = new Date();
@NotNull @ManyToOne
private User user; private User user;
public Project() { public Project() {

View File

@ -1,9 +1,14 @@
package ru.ulstu.fc.project.repository; package ru.ulstu.fc.project.repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import ru.ulstu.fc.project.model.Project; import ru.ulstu.fc.project.model.Project;
import java.util.List;
@Repository @Repository
public interface ProjectRepository extends JpaRepository<Project, Integer> { public interface ProjectRepository extends JpaRepository<Project, Integer> {
List<Project> findAllByUserId(@Param("userId") Integer userId);
} }

View File

@ -4,48 +4,61 @@ import org.springframework.stereotype.Service;
import ru.ulstu.fc.project.model.Project; import ru.ulstu.fc.project.model.Project;
import ru.ulstu.fc.project.model.ProjectForm; import ru.ulstu.fc.project.model.ProjectForm;
import ru.ulstu.fc.project.repository.ProjectRepository; import ru.ulstu.fc.project.repository.ProjectRepository;
import ru.ulstu.fc.user.utils.UserUtils; import ru.ulstu.fc.user.model.User;
import ru.ulstu.fc.user.service.UserService;
import java.util.List; import java.util.List;
@Service @Service
public class ProjectService { public class ProjectService {
private final ProjectRepository projectRepository; private final ProjectRepository projectRepository;
private final UserService userService;
public ProjectService(ProjectRepository projectRepository) { public ProjectService(ProjectRepository projectRepository,
UserService userService) {
this.projectRepository = projectRepository; this.projectRepository = projectRepository;
this.userService = userService;
} }
public List<Project> getCurrentUserProjects() { public List<Project> getCurrentUserProjects() {
return projectRepository.findAll(); return projectRepository.findAllByUserId(userService.getCurrentUser().getId());
}
public Project getById(Integer id) {
Project project = projectRepository
.findById(id)
.orElseThrow(() -> new RuntimeException("Project not found by id"));
checkUserProjectWithThrow(project, userService.getCurrentUser());
return project;
} }
public Project save(ProjectForm projectForm) { public Project save(ProjectForm projectForm) {
return projectRepository.save(new Project(projectForm)); return save(new Project(projectForm));
} }
public Project save(Project projectToSave) { public Project save(Project projectToSave) {
User currentUser = userService.getCurrentUser();
if (projectToSave.getId() == null) { if (projectToSave.getId() == null) {
projectToSave.setUser(currentUser);
return projectRepository.save(projectToSave); return projectRepository.save(projectToSave);
} }
Project dbProject = projectRepository Project dbProject = getById(projectToSave.getId());
.findById(projectToSave.getId())
.orElseThrow(() -> new RuntimeException("Project not found by id"));
dbProject.setName(projectToSave.getName()); dbProject.setName(projectToSave.getName());
return projectRepository.save(dbProject); return projectRepository.save(dbProject);
} }
public void delete(ProjectForm projectForm) { public void delete(ProjectForm projectForm) {
getById(projectForm.getId());
projectRepository.deleteById(projectForm.getId()); projectRepository.deleteById(projectForm.getId());
} }
private void checkUserProjectWithThrow(Project project) { private void checkUserProjectWithThrow(Project project, User currentUser) {
if (!isUserProject(project)) { if (!isUserProject(project, currentUser)) {
throw new RuntimeException("User can not get access to project"); throw new RuntimeException("User can not get access to project");
} }
} }
private boolean isUserProject(Project project) { private boolean isUserProject(Project project, User currentUser) {
return (UserUtils.getCurrentUserLogin().equals(project.getUser().getLogin())); return (currentUser.equals(project.getUser()));
} }
} }

View File

@ -15,6 +15,7 @@ import ru.ulstu.fc.user.model.UserRole;
import ru.ulstu.fc.user.model.UserRoleConstants; import ru.ulstu.fc.user.model.UserRoleConstants;
import ru.ulstu.fc.user.repository.UserRepository; import ru.ulstu.fc.user.repository.UserRepository;
import ru.ulstu.fc.user.repository.UserRoleRepository; import ru.ulstu.fc.user.repository.UserRoleRepository;
import ru.ulstu.fc.user.utils.UserUtils;
import java.util.Collections; import java.util.Collections;
import java.util.Optional; import java.util.Optional;
@ -85,4 +86,8 @@ public class UserService implements UserDetailsService {
public void initDefaultAdmin() { public void initDefaultAdmin() {
createDefaultUser("admin", UserRoleConstants.ADMIN); createDefaultUser("admin", UserRoleConstants.ADMIN);
} }
public User getCurrentUser() {
return getUserByLogin(UserUtils.getCurrentUserLogin());
}
} }