parent
ba952bb1f8
commit
fce631eb3c
@ -0,0 +1,78 @@
|
|||||||
|
package edu.ahbvc.recruit.aspect;
|
||||||
|
|
||||||
|
import edu.ahbvc.recruit.annotation.SwitchMethod;
|
||||||
|
import edu.ahbvc.recruit.model.ApiResponseData;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author c215
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class MethodSwitch {
|
||||||
|
// 使用常量定义功能类型
|
||||||
|
// 注册
|
||||||
|
public static final String REGISTER = "register";
|
||||||
|
// 提交简历
|
||||||
|
public static final String SUBMIT = "submit";
|
||||||
|
// 尝试重新提交
|
||||||
|
public static final String TRY_SUBMIT = "trySubmit";
|
||||||
|
// 放弃投递
|
||||||
|
public static final String ABANDON = "abandon";
|
||||||
|
|
||||||
|
// 使用带有默认值的线程安全的Map存储开关状态
|
||||||
|
private static final Map<String, Boolean> METHOD_SWITCHES = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
// 静态代码块,在类加载时执行,用于初始化开关状态
|
||||||
|
static {
|
||||||
|
// 默认情况下,所有功能都启用
|
||||||
|
METHOD_SWITCHES.put(REGISTER, true);
|
||||||
|
METHOD_SWITCHES.put(SUBMIT, true);
|
||||||
|
METHOD_SWITCHES.put(TRY_SUBMIT, true);
|
||||||
|
METHOD_SWITCHES.put(ABANDON, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一设置方法
|
||||||
|
// 通过此方法可以动态地设置功能的开关状态
|
||||||
|
public static void setSwitch(String methodType, boolean enabled) {
|
||||||
|
// 检查方法类型是否存在
|
||||||
|
if (!METHOD_SWITCHES.containsKey(methodType)) {
|
||||||
|
throw new IllegalArgumentException("Invalid method type: " + methodType);
|
||||||
|
}
|
||||||
|
// 设置功能的开关状态
|
||||||
|
METHOD_SWITCHES.put(methodType, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一获取方法
|
||||||
|
// 通过此方法可以获取功能的开关状态
|
||||||
|
public static boolean isEnabled(String methodType) {
|
||||||
|
// 检查方法类型是否存在
|
||||||
|
if (!METHOD_SWITCHES.containsKey(methodType)) {
|
||||||
|
throw new IllegalArgumentException("Invalid method type: " + methodType);
|
||||||
|
}
|
||||||
|
// 返回功能的开关状态
|
||||||
|
return METHOD_SWITCHES.getOrDefault(methodType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一切面处理
|
||||||
|
@Around("@annotation(switchMethod)")
|
||||||
|
public Object controlMethod(ProceedingJoinPoint joinPoint, SwitchMethod switchMethod) throws Throwable {
|
||||||
|
// 获取方法的功能类型
|
||||||
|
String methodType = switchMethod.value();
|
||||||
|
// 检查功能是否启用
|
||||||
|
if (!METHOD_SWITCHES.getOrDefault(methodType, false)) {
|
||||||
|
// 如果功能未启用,则返回错误信息
|
||||||
|
return new ApiResponseData<>("500", null, "此功能已关闭");
|
||||||
|
}
|
||||||
|
// 如果功能已启用,则执行原方法
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
|||||||
|
package edu.ahbvc.recruit.config;
|
||||||
|
|
||||||
|
import edu.ahbvc.recruit.util.JwtUtil;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT请求过滤器
|
||||||
|
* 用于处理JWT认证请求
|
||||||
|
* 继承自OncePerRequestFilter, 确保每个请求只被过滤一次
|
||||||
|
* 实现了doFilterInternal方法, 用于处理请求的认证逻辑
|
||||||
|
* 从请求头中获取JWT令牌, 并验证令牌的有效性
|
||||||
|
* 如果令牌有效, 则将用户信息设置到SecurityContextHolder中, 以便后续的认证和授权操作
|
||||||
|
* 如果令牌无效, 则不做任何操作
|
||||||
|
* 因为JWT相关代码暂未更新, 所以此类用不到
|
||||||
|
* 更新了之后代码量更少了,所以屎山了, 但是功能是有的, 所以就先这样了, 以后再优化
|
||||||
|
* @author c215
|
||||||
|
*/
|
||||||
|
|
||||||
|
// * JWT请求过滤器
|
||||||
|
// * 用于处理JWT认证请求
|
||||||
|
// * 继承自OncePerRequestFilter, 确保每个请求只被过滤一次
|
||||||
|
// * 实现了doFilterInternal方法, 用于处理请求的认证逻辑
|
||||||
|
// * 从请求头中获取JWT令牌, 并验证令牌的有效性
|
||||||
|
// * 如果令牌有效, 则将用户信息设置到SecurityContextHolder中, 以便后续的认证和授权操作
|
||||||
|
// * 如果令牌无效, 则不做任何操作
|
||||||
|
// * 因为JWT相关代码暂未更新, 所以此类用不到
|
||||||
|
// * 更新了之后代码量更少了,所以屎山了, 但是功能是有的, 所以就先这样了, 以后再优化
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtRequestFilter {
|
||||||
|
// extends OncePerRequestFilter
|
||||||
|
// @Autowired
|
||||||
|
// private UserDetailsService userDetailsService;
|
||||||
|
//
|
||||||
|
// @Autowired
|
||||||
|
// private JwtUtil jwtUtil;
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||||
|
// throws ServletException, IOException {
|
||||||
|
//
|
||||||
|
// final String authorizationHeader = request.getHeader("Authorization");
|
||||||
|
//
|
||||||
|
// String username = null;
|
||||||
|
// String jwt = null;
|
||||||
|
//
|
||||||
|
// if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
|
||||||
|
// jwt = authorizationHeader.substring(7);
|
||||||
|
// username = jwtUtil.extractUsername(jwt);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
//
|
||||||
|
// UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||||
|
//
|
||||||
|
// if (jwtUtil.validateToken(jwt, userDetails)) {
|
||||||
|
//
|
||||||
|
// UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
|
||||||
|
// userDetails, null, userDetails.getAuthorities());
|
||||||
|
// usernamePasswordAuthenticationToken
|
||||||
|
// .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
// SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// chain.doFilter(request, response);
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package edu.ahbvc.recruit.config;
|
||||||
|
|
||||||
|
|
||||||
|
import edu.ahbvc.recruit.mapper.UserInter;
|
||||||
|
import edu.ahbvc.recruit.model.token.CustomUserDetailsService;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.CachingUserDetailsService;
|
||||||
|
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.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
|
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring Security配置类
|
||||||
|
* @author c215
|
||||||
|
*/
|
||||||
|
// @Configuration 表示这是一个配置类
|
||||||
|
@Configuration
|
||||||
|
// @EnableWebSecurity 表示启用Spring Security的Web安全支持
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class Security {
|
||||||
|
// SecurityFilterChain 用于配置安全过滤器链
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
|
.cors(withDefaults())
|
||||||
|
.authorizeHttpRequests((requests)->requests
|
||||||
|
.requestMatchers("/","/login","/favicon.ico","/**").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
|
||||||
|
)
|
||||||
|
.formLogin((form)-> form
|
||||||
|
.loginPage("/login.html")
|
||||||
|
.permitAll()
|
||||||
|
);
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// CORS 配置源 用于配置跨域请求的CORS配置
|
||||||
|
// 正式上线后需要修改为允许指定的域名和端口
|
||||||
|
@Bean
|
||||||
|
CorsConfigurationSource corsConfigurationSource() {
|
||||||
|
CorsConfiguration configuration = new CorsConfiguration();
|
||||||
|
// 允许所有本地地址和端口
|
||||||
|
configuration.setAllowedOriginPatterns(Arrays.asList(
|
||||||
|
"http://localhost:*",
|
||||||
|
"http://127.0.0.1:*"
|
||||||
|
));
|
||||||
|
// 允许所有请求方法
|
||||||
|
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||||
|
// 允许所有请求头
|
||||||
|
configuration.setAllowedHeaders(Collections.singletonList("*"));
|
||||||
|
// 允许携带凭证
|
||||||
|
configuration.setAllowCredentials(true);
|
||||||
|
|
||||||
|
// 注册CORS配置源
|
||||||
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
// 注册CORS配置源
|
||||||
|
source.registerCorsConfiguration("/**", configuration);
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserDetailsService 用于加载用户信息
|
||||||
|
// 因为JWT相关代码暂未更新, 所以此方法用不到
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService userDetailsService(UserInter userRepository){
|
||||||
|
return new CustomUserDetailsService(userRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder(){
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package edu.ahbvc.recruit.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web配置
|
||||||
|
* @author c215
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
// 配置跨域请求的CORS配置
|
||||||
|
// 正式上线后需要修改为允许指定的域名和端口
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**")
|
||||||
|
// 允许所有本地地址和端口
|
||||||
|
.allowedOrigins("http://localhost:3333")
|
||||||
|
// 允许的请求方法
|
||||||
|
.allowedMethods("GET", "POST", "PUT", "DELETE")
|
||||||
|
// 允许的请求头
|
||||||
|
.allowedHeaders("*")
|
||||||
|
// 允许凭证
|
||||||
|
.allowCredentials(true)
|
||||||
|
// 预检请求的缓存时间
|
||||||
|
.maxAge(3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置静态资源的处理
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
|
// 配置静态资源的处理
|
||||||
|
// 允许访问的路径
|
||||||
|
registry.addResourceHandler("/**")
|
||||||
|
// 允许访问的路径
|
||||||
|
.addResourceLocations("classpath:/static/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in new issue