#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.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
@EnableConfigurationProperties
public class FuzzyControllerApplication {
private final UserService userService;
public FuzzyControllerApplication(UserService userService) {
this.userService = userService;
}
public static void main(String[] 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;
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.config.annotation.InterceptorRegistry;
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.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login");
registry.addViewController("/loginError");
registry.addViewController("/index");
}
@Override
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;
import io.swagger.v3.oas.annotations.Hidden;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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 ru.ulstu.fc.project.model.ProjectForm;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.user.model.UserRoleConstants;
@Controller
@Hidden
@RequestMapping("project")
@Secured({UserRoleConstants.ADMIN})
public class ProjectController {
private final ProjectService projectService;

View File

@ -1,5 +1,6 @@
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.GetMapping;
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.ProjectForm;
import ru.ulstu.fc.project.service.ProjectService;
import ru.ulstu.fc.user.model.UserRoleConstants;
import java.util.List;
@RestController
@RequestMapping("projectRest")
@Secured({UserRoleConstants.ADMIN})
public class ProjectRestController {
private final ProjectService projectService;

View File

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

View File

@ -1,9 +1,14 @@
package ru.ulstu.fc.project.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import ru.ulstu.fc.project.model.Project;
import java.util.List;
@Repository
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.ProjectForm;
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;
@Service
public class ProjectService {
private final ProjectRepository projectRepository;
private final UserService userService;
public ProjectService(ProjectRepository projectRepository) {
public ProjectService(ProjectRepository projectRepository,
UserService userService) {
this.projectRepository = projectRepository;
this.userService = userService;
}
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) {
return projectRepository.save(new Project(projectForm));
return save(new Project(projectForm));
}
public Project save(Project projectToSave) {
User currentUser = userService.getCurrentUser();
if (projectToSave.getId() == null) {
projectToSave.setUser(currentUser);
return projectRepository.save(projectToSave);
}
Project dbProject = projectRepository
.findById(projectToSave.getId())
.orElseThrow(() -> new RuntimeException("Project not found by id"));
Project dbProject = getById(projectToSave.getId());
dbProject.setName(projectToSave.getName());
return projectRepository.save(dbProject);
}
public void delete(ProjectForm projectForm) {
getById(projectForm.getId());
projectRepository.deleteById(projectForm.getId());
}
private void checkUserProjectWithThrow(Project project) {
if (!isUserProject(project)) {
private void checkUserProjectWithThrow(Project project, User currentUser) {
if (!isUserProject(project, currentUser)) {
throw new RuntimeException("User can not get access to project");
}
}
private boolean isUserProject(Project project) {
return (UserUtils.getCurrentUserLogin().equals(project.getUser().getLogin()));
private boolean isUserProject(Project project, User currentUser) {
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.repository.UserRepository;
import ru.ulstu.fc.user.repository.UserRoleRepository;
import ru.ulstu.fc.user.utils.UserUtils;
import java.util.Collections;
import java.util.Optional;
@ -85,4 +86,8 @@ public class UserService implements UserDetailsService {
public void initDefaultAdmin() {
createDefaultUser("admin", UserRoleConstants.ADMIN);
}
public User getCurrentUser() {
return getUserByLogin(UserUtils.getCurrentUserLogin());
}
}