拆分模块

This commit is contained in:
2025-09-03 20:56:44 +08:00
parent 08cc2c29a5
commit a2f5e4864b
939 changed files with 14227 additions and 9607 deletions

View File

@@ -0,0 +1,38 @@
package com.ecep.contract.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import java.util.List;
/**
* OpenAPI配置类用于配置Swagger文档
*/
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("合同管理系统 API")
.version("1.0")
.description("合同管理系统的REST API文档")
.contact(new Contact()
.name("宋其青")
.email("qiqing.song@ecep.com"))
.license(new License()
.name("内部使用")
.url("http://10.84.210.110")))
.servers(List.of(
new Server().url("http://localhost:8080").description("开发环境"),
new Server().url("http://10.84.210.110:8080").description("测试环境")
));
}
}

View File

@@ -0,0 +1,160 @@
package com.ecep.contract.config;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.Customizer;
import com.ecep.contract.ds.other.service.EmployeeService;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.EmployeeRole;
/**
* Spring Security配置类
* 用于配置安全认证和授权规则
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Lazy
@Autowired
private EmployeeService employeeService;
/**
* 配置HTTP安全策略
* 启用表单登录和HTTP Basic认证
*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/login.html", "/css/**", "/js/**", "/images/**", "/webjars/**", "/login", "/error").permitAll() // 允许静态资源、登录页面和错误页面访问
.anyRequest().authenticated() // 其他所有请求需要认证
)
.csrf(AbstractHttpConfigurer::disable) // 禁用CSRF保护适合开发环境
.formLogin(form -> form
.loginPage("/login.html") // 直接使用静态登录页面
.loginProcessingUrl("/login") // 登录处理URL
.permitAll() // 允许所有人访问登录页面
.defaultSuccessUrl("/", true) // 登录成功后重定向到首页
.failureUrl("/login.html?error=true") // 登录失败后重定向到登录页面并显示错误
.usernameParameter("username") // 用户名参数名
.passwordParameter("password") // 密码参数名
)
.httpBasic(Customizer.withDefaults()) // 启用HTTP Basic认证
.logout(logout -> logout
.logoutUrl("/logout") // 注销URL
.logoutSuccessUrl("/login?logout=true") // 注销成功后重定向到登录页面
.invalidateHttpSession(true) // 使会话失效
.deleteCookies("JSESSIONID") // 删除会话cookie
.permitAll() // 允许所有人访问注销URL
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // 根据需要创建会话
.maximumSessions(1) // 每个用户最多1个会话
.expiredUrl("/login?expired=true") // 会话过期后重定向到登录页面
)
.authenticationManager(authenticationManager); // 设置认证管理器
return http.build();
}
/**
* 配置AuthenticationManager
* 用于处理认证请求
*/
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
/**
* 配置密码编码器
* BCryptPasswordEncoder是Spring Security推荐的密码编码器
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 配置基于EmployeeService的用户认证
* 通过EmployeeService获取员工信息并转换为Spring Security的UserDetails
*/
@Bean
public UserDetailsService userDetailsService() {
return username -> {
// 使用EmployeeService根据用户名查找员工
Employee employee = employeeService.findByAccount(username);
// 如果找不到员工抛出UsernameNotFoundException异常
if (employee == null) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
// 检查员工是否活跃
if (!employee.isActive()) {
throw new UsernameNotFoundException("用户已禁用: " + username);
}
// 将员工角色转换为Spring Security的GrantedAuthority
List<GrantedAuthority> authorities = getAuthoritiesFromRoles(employee.getRoles());
// 创建并返回UserDetails对象
// 注意根据系统设计Employee实体中没有密码字段系统使用IP/MAC绑定认证
// 这里使用密码编码器加密后的固定密码,确保认证流程能够正常工作
return User.builder()
.username(employee.getName())
.password(passwordEncoder().encode("default123")) // 使用默认密码进行加密
.authorities(authorities)
.build();
};
}
/**
* 将EmployeeRole列表转换为Spring Security的GrantedAuthority列表
*/
private List<GrantedAuthority> getAuthoritiesFromRoles(List<EmployeeRole> roles) {
if (roles == null || roles.isEmpty()) {
return List.of();
}
// 为每个角色创建GrantedAuthority
// 系统管理员拥有ADMIN角色其他用户拥有USER角色
return roles.stream()
.filter(EmployeeRole::isActive) // 只包含活跃的角色
.map(role -> {
if (role.isSystemAdministrator()) {
return new SimpleGrantedAuthority("ROLE_ADMIN");
} else {
return new SimpleGrantedAuthority("ROLE_USER");
}
})
.collect(Collectors.toList());
}
// Spring Security会自动配置一个使用我们定义的UserDetailsService的DaoAuthenticationProvider
// 移除显式的authenticationProvider Bean定义以避免警告
// 当同时存在AuthenticationProvider和UserDetailsService Bean时Spring Security会优先使用AuthenticationProvider
// 而忽略直接的UserDetailsService虽然这不影响功能但会产生警告
}

View File

@@ -0,0 +1,39 @@
package com.ecep.contract.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web配置类提供CORS支持等Web相关配置
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 配置跨域资源共享(CORS)
*/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
// 允许所有来源
config.addAllowedOriginPattern("*");
// 允许所有请求头
config.addAllowedHeader("*");
// 允许所有HTTP方法
config.addAllowedMethod("*");
// 允许发送Cookie
config.setAllowCredentials(true);
// 设置预检请求的有效期(秒)
config.setMaxAge(3600L);
// 应用配置到所有路径
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}