diff --git a/ApiGateway.java b/ApiGateway.java new file mode 100644 index 0000000..4484ad2 --- /dev/null +++ b/ApiGateway.java @@ -0,0 +1,584 @@ +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.util.*; + +/** + * API网关 - 聚合多个服务,包含架构和安全问题 + */ +public class ApiGateway { + + private UserService userService; + private UserManager userManager; + private RestController restController; + private DataValidator dataValidator; + private CacheManager cacheManager; + private AuditLogger auditLogger; + private ConfigService configService; + + // 服务发现但硬编码依赖 + private Map serviceRegistry = new HashMap<>(); + + public ApiGateway() { + initializeServices(); + registerRoutes(); + } + + // 初始化所有服务但可能循环依赖 + private void initializeServices() { + this.userService = new UserService(); + this.userManager = new UserManager(); // UserManager可能未正确初始化 + this.restController = new RestController(); + this.dataValidator = new DataValidator(); + this.cacheManager = CacheManager.getInstance(); // 可能循环依赖 + this.auditLogger = AuditLogger.getInstance(); + this.configService = ConfigService.getInstance(); + + // 注册服务但没有生命周期管理 + serviceRegistry.put("users", userService); + serviceRegistry.put("validation", dataValidator); + serviceRegistry.put("cache", cacheManager); + } + + private void registerRoutes() { + // 路由注册逻辑,但没有实际实现 + } + + // 统一入口但安全检查不足 + public String handleRequest(String endpoint, HttpServletRequest request, HttpServletResponse response) { + String startTime = String.valueOf(System.currentTimeMillis()); + + try { + // 基本的速率限制检查,但实现有漏洞 + if (!checkRateLimit(request)) { + return "Rate limit exceeded"; + } + + // 路由分发但没有权限检查 + String result = routeRequest(endpoint, request, response); + + // 记录请求但可能泄漏敏感信息 + auditLogger.logWebRequest(endpoint, "unknown", request.getQueryString()); + + return result; + + } catch (Exception e) { + // 异常处理类似RestController的问题 + auditLogger.logError("API Gateway error", e); + return "Internal server error: " + e.getMessage(); // 泄漏内部信息 + } + } + + // 路由分发但API不一致 + private String routeRequest(String endpoint, HttpServletRequest request, HttpServletResponse response) { + switch (endpoint) { + case "/api/users/create": + return handleUserCreation(request, response); + case "/api/users/get": + return handleUserRetrieval(request); + case "/api/users/validate": + return handleUserValidation(request); + case "/api/cache/get": + return handleCacheGet(request); + case "/api/files/upload": + return handleFileUpload(request); + default: + return "Unknown endpoint: " + endpoint; + } + } + + // 用户创建聚合多个服务但问题叠加 + private String handleUserCreation(HttpServletRequest request, HttpServletResponse response) { + String name = request.getParameter("name"); + String email = request.getParameter("email"); + String password = request.getParameter("password"); + + // 使用DataValidator验证,但可能有空指针问题 + DataValidator.ValidationResult validation = dataValidator.validateUser( + new UserService.User(name, email, password)); + + if (!validation.isValid()) { + // 返回详细验证错误,可能泄漏信息 + return "Validation failed: " + validation.getErrors().toString(); + } + + // 同时调用UserService和RestController,逻辑重复 + userService.createUser(name, email, password, null, null); + String restResult = restController.createUser(request, response); + + // 缓存新用户但可能缓存敏感信息 + cacheManager.cacheUser(email, new UserService.User(name, email, password)); + + return "User created successfully"; + } + + // 用户检索但API类型不匹配 + private String handleUserRetrieval(HttpServletRequest request) { + String userId = request.getParameter("userId"); + + // 尝试从缓存获取 + UserService.User cachedUser = cacheManager.getCachedUser(userId); + if (cachedUser != null) { + // 返回用户信息但可能包含密码 + return cachedUser.toString(); + } + + // UserService.getUserById需要String,UserManager.getUser需要int + UserService.User user1 = userService.getUserById(userId); + try { + int userIdInt = Integer.parseInt(userId); + UserService.User user2 = userManager.getUser(userIdInt); + + // 两个结果可能不一致 + if (user1 != null && user2 != null) { + if (!userManager.isDuplicateUser(user1, user2)) { // equals未重写,总是false + auditLogger.logError("Inconsistent user data", null); + } + } + } catch (NumberFormatException e) { + // 忽略类型转换错误 + } + + return user1 != null ? user1.toString() : "User not found"; + } + + // 用户验证但重复多个验证逻辑 + private String handleUserValidation(HttpServletRequest request) { + String email = request.getParameter("email"); + String password = request.getParameter("password"); + + // 使用多个不同的验证方法,结果可能不一致 + boolean emailValid1 = dataValidator.validateEmail(email); + boolean emailValid2 = StringUtils.isValidEmail(email); // 不同的验证逻辑 + + if (emailValid1 != emailValid2) { + auditLogger.logSecurity("Email validation inconsistency", email); + } + + // 密码验证也使用多种方法 + DataValidator.ValidationResult passwordResult = dataValidator.validatePassword(password); + boolean passwordValid2 = StringUtils.isValidPassword(password); + + // 同时进行登录验证,但RestController可能泄漏信息 + String loginResult = restController.login(request); + + return "Validation completed"; + } + + // 缓存操作但暴露内部实现 + private String handleCacheGet(HttpServletRequest request) { + String key = request.getParameter("key"); + + if (StringUtils.isEmpty(key)) { // 空指针风险 + return "Invalid cache key"; + } + + // 直接暴露缓存内容,可能包含敏感数据 + Object cached = cacheManager.get(key); + + if (cached != null) { + return "Cache hit: " + cached.toString(); + } else { + return "Cache miss"; + } + } + + // 文件上传聚合但安全问题叠加 + private String handleFileUpload(HttpServletRequest request) { + String fileName = request.getParameter("fileName"); + String content = request.getParameter("content"); + + // 使用DataValidator验证文件路径,但验证不够 + if (!dataValidator.validateFilePath(fileName)) { + return "Invalid file path"; + } + + // 同时使用RestController和FileProcessor,问题叠加 + String restResult = restController.uploadFile(request); + + FileProcessor processor = new FileProcessor(); + try { + processor.writeFile(fileName, content); // 资源泄漏 + } catch (Exception e) { + auditLogger.logFileOperation(fileName, "upload_failed"); + } + + // 缓存文件内容但可能很大 + cacheManager.put("file_" + fileName, content); + + return "File uploaded successfully"; + } + + // 速率限制但实现有漏洞 + private boolean checkRateLimit(HttpServletRequest request) { + String clientIp = request.getRemoteAddr(); + String cacheKey = "rate_limit_" + clientIp; + + // 使用缓存计数,但计数逻辑有问题 + Object countObj = cacheManager.get(cacheKey); + int count = countObj instanceof Integer ? (Integer) countObj : 0; + + count++; + cacheManager.put(cacheKey, count); + + // 硬编码限制,没有配置 + return count <= 100; + } + + // 健康检查但检查不全面 + public Map healthCheck() { + Map health = new HashMap<>(); + + // 检查各个服务但可能触发其问题 + try { + // 检查数据库连接,但可能资源泄漏 + DatabaseConnection.getConnection(); + health.put("database", "healthy"); + } catch (Exception e) { + health.put("database", "unhealthy: " + e.getMessage()); + } + + // 检查缓存 + CacheManager.CacheStats stats = cacheManager.getStatistics(); + health.put("cache", stats.toString()); + + // 检查配置服务 + String dbUrl = configService.getConfigValue("db.url"); + health.put("config", StringUtils.isEmpty(dbUrl) ? "missing config" : "configured"); + + return health; + } + + // 批量操作但没有事务管理 + public String handleBatch(List> requests) { + List results = new ArrayList<>(); + + for (Map requestData : requests) { + String endpoint = requestData.get("endpoint"); + + // 为每个请求创建模拟的HttpServletRequest,但实现有问题 + MockHttpServletRequest mockRequest = new MockHttpServletRequest(requestData); + + try { + String result = routeRequest(endpoint, mockRequest, null); + results.add(result); + } catch (Exception e) { + // 某个请求失败但继续处理其他请求,可能导致不一致状态 + results.add("Error: " + e.getMessage()); + } + } + + return "Batch completed: " + results.size() + " requests processed"; + } + + // 服务监控但可能泄漏内部信息 + public String getServiceStatus() { + StringBuilder status = new StringBuilder(); + + for (Map.Entry entry : serviceRegistry.entrySet()) { + status.append(entry.getKey()).append(": "); + + // 调用toString可能泄漏内部状态 + status.append(entry.getValue().toString()).append("\n"); + } + + return status.toString(); + } + + // 清理方法但清理不完整 + public void shutdown() { + auditLogger.cleanup(); + cacheManager.clearAll(); + + // 其他服务没有清理 + // userService等没有清理方法 + } + + // 简单的模拟HttpServletRequest + private static class MockHttpServletRequest implements HttpServletRequest { + private Map parameters; + + public MockHttpServletRequest(Map parameters) { + this.parameters = parameters; + } + + @Override + public String getParameter(String name) { + return parameters.get(name); + } + + @Override + public String getRemoteAddr() { + return "127.0.0.1"; // 硬编码 + } + + @Override + public String getQueryString() { + // 简单实现,可能不正确 + StringBuilder query = new StringBuilder(); + for (Map.Entry entry : parameters.entrySet()) { + if (query.length() > 0) + query.append("&"); + query.append(entry.getKey()).append("=").append(entry.getValue()); + } + return query.toString(); + } + + // 其他HttpServletRequest方法的空实现 + public String getAuthType() { + return null; + } + + public javax.servlet.http.Cookie[] getCookies() { + return null; + } + + public long getDateHeader(String name) { + return 0; + } + + public String getHeader(String name) { + return null; + } + + public Enumeration getHeaders(String name) { + return null; + } + + public Enumeration getHeaderNames() { + return null; + } + + public int getIntHeader(String name) { + return 0; + } + + public String getMethod() { + return "GET"; + } + + public String getPathInfo() { + return null; + } + + public String getPathTranslated() { + return null; + } + + public String getContextPath() { + return null; + } + + public String getRequestedSessionId() { + return null; + } + + public String getRequestURI() { + return null; + } + + public StringBuffer getRequestURL() { + return null; + } + + public String getServletPath() { + return null; + } + + public javax.servlet.http.HttpSession getSession(boolean create) { + return null; + } + + public javax.servlet.http.HttpSession getSession() { + return null; + } + + public String changeSessionId() { + return null; + } + + public boolean isRequestedSessionIdValid() { + return false; + } + + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + public boolean isRequestedSessionIdFromURL() { + return false; + } + + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + public boolean authenticate(HttpServletResponse response) { + return false; + } + + public void login(String username, String password) { + } + + public void logout() { + } + + public java.util.Collection getParts() { + return null; + } + + public javax.servlet.http.Part getPart(String name) { + return null; + } + + public T upgrade(Class handlerClass) { + return null; + } + + public Object getAttribute(String name) { + return null; + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getCharacterEncoding() { + return null; + } + + public void setCharacterEncoding(String env) { + } + + public int getContentLength() { + return 0; + } + + public long getContentLengthLong() { + return 0; + } + + public String getContentType() { + return null; + } + + public javax.servlet.ServletInputStream getInputStream() { + return null; + } + + public String[] getParameterValues(String name) { + return null; + } + + public Map getParameterMap() { + return null; + } + + public Enumeration getParameterNames() { + return null; + } + + public String getProtocol() { + return null; + } + + public String getScheme() { + return null; + } + + public String getServerName() { + return null; + } + + public int getServerPort() { + return 0; + } + + public java.io.BufferedReader getReader() { + return null; + } + + public String getRealPath(String path) { + return null; + } + + public int getRemotePort() { + return 0; + } + + public String getLocalName() { + return null; + } + + public String getLocalAddr() { + return null; + } + + public int getLocalPort() { + return 0; + } + + public javax.servlet.ServletContext getServletContext() { + return null; + } + + public javax.servlet.AsyncContext startAsync() { + return null; + } + + public javax.servlet.AsyncContext startAsync(javax.servlet.ServletRequest servletRequest, + javax.servlet.ServletResponse servletResponse) { + return null; + } + + public boolean isAsyncStarted() { + return false; + } + + public boolean isAsyncSupported() { + return false; + } + + public javax.servlet.AsyncContext getAsyncContext() { + return null; + } + + public javax.servlet.DispatcherType getDispatcherType() { + return null; + } + + public void setAttribute(String name, Object o) { + } + + public void removeAttribute(String name) { + } + + public java.util.Locale getLocale() { + return null; + } + + public Enumeration getLocales() { + return null; + } + + public boolean isSecure() { + return false; + } + + public javax.servlet.RequestDispatcher getRequestDispatcher(String path) { + return null; + } + + public String getRemoteUser() { + return null; + } + + public boolean isUserInRole(String role) { + return false; + } + + public java.security.Principal getUserPrincipal() { + return null; + } + } +} diff --git a/AuditLogger.java b/AuditLogger.java new file mode 100644 index 0000000..0ede1e4 --- /dev/null +++ b/AuditLogger.java @@ -0,0 +1,252 @@ +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 审计日志器 - 引用多个现有类,包含日志和监控问题 + */ +public class AuditLogger { + + private static final String LOG_FORMAT = "yyyy-MM-dd HH:mm:ss"; // 与其他类时间格式不一致 + private FileProcessor fileProcessor; + private ConfigService configService; + private List logBuffer = new ArrayList<>(); + + // 依赖注入问题 + public AuditLogger() { + this.fileProcessor = new FileProcessor(); + this.configService = ConfigService.getInstance(); // 可能的循环依赖 + } + + // 记录UserService操作但暴露敏感信息 + public void logUserOperation(String operation, UserService.User user) { + String timestamp = getCurrentTimestamp(); + + // 直接记录用户信息,包含密码 - 与UserService.toString问题相关 + String logEntry = String.format("[%s] User Operation: %s - User: %s", + timestamp, operation, user.toString()); // 泄漏密码 + + addToBuffer(logEntry); + + // 与StringUtils的不当使用 + if (!StringUtils.isEmpty(user.email)) { // 空指针风险 + logUserEmail(user.email); + } + } + + // 记录DatabaseConnection操作 + public void logDatabaseOperation(String sql, boolean success) { + String timestamp = getCurrentTimestamp(); + + // 记录完整SQL,可能包含敏感数据 + String logEntry = String.format("[%s] DB Operation: %s - Success: %s", + timestamp, sql, success); + + addToBuffer(logEntry); + + if (!success) { + // 调用DatabaseConnection的方法进行重试,但可能导致资源泄漏 + try { + DatabaseConnection.getConnection(); // 创建连接但不关闭 + } catch (Exception e) { + logError("Failed to reconnect to database", e); + } + } + } + + // 记录Calculator计算但有精度问题 + public void logCalculation(String operation, double result) { + String timestamp = getCurrentTimestamp(); + + Calculator calc = new Calculator(); + + // 使用Calculator的有问题方法检查结果 + if (calc.isEqual(result, Double.NaN)) { // 错误的NaN检查 + logError("Invalid calculation result", null); + return; + } + + // 记录计算结果但可能精度丢失 + String logEntry = String.format("[%s] Calculation: %s = %.2f", + timestamp, operation, result); + + addToBuffer(logEntry); + } + + // 记录文件操作但重复FileProcessor的问题 + public void logFileOperation(String fileName, String operation) { + String timestamp = getCurrentTimestamp(); + + // 使用FileProcessor验证文件,但方法有问题 + if (!fileProcessor.isValidFile(fileName)) { // 只检查存在性,不够全面 + logError("Invalid file operation attempted: " + fileName, null); + } + + String logEntry = String.format("[%s] File Operation: %s on %s", + timestamp, operation, fileName); + + addToBuffer(logEntry); + + // 尝试读取文件记录详细信息,但可能内存问题 + try { + List lines = fileProcessor.readAllLines(fileName); // 大文件内存问题 + logEntry += String.format(" - Lines: %d", lines.size()); + } catch (Exception e) { + // 忽略读取错误 + } + } + + // 记录并发操作但线程安全问题 + public void logConcurrentOperation(String threadName, String operation) { + String timestamp = getCurrentTimestamp(); + + ConcurrentTask task = ConcurrentTask.getInstance(); // 单例线程安全问题 + task.incrementCounter(); // 竞态条件 + + String logEntry = String.format("[%s] Thread %s: %s - Counter: %d", + timestamp, threadName, operation, task.getCounter()); + + // 非线程安全的操作 + logBuffer.add(logEntry); // ArrayList在并发环境中不安全 + } + + // 记录Web请求但包含安全问题 + public void logWebRequest(String endpoint, String userRole, String params) { + String timestamp = getCurrentTimestamp(); + + // 直接记录请求参数,可能包含敏感信息 - 类似RestController问题 + String logEntry = String.format("[%s] Web Request: %s - Role: %s - Params: %s", + timestamp, endpoint, userRole, params); // 可能记录密码等敏感参数 + + addToBuffer(logEntry); + + // 使用StringUtils清理但方法有问题 + String sanitized = StringUtils.sanitizeInput(params); // 不完整的清理 + + if (!sanitized.equals(params)) { + logSecurity("Potential XSS attempt detected", params); + } + } + + // 记录数据处理但反射问题 + public void logDataProcessing(Object data, String type) { + String timestamp = getCurrentTimestamp(); + + DataProcessor processor = DataProcessor.getInstance(); + + try { + // 使用反射记录对象详细信息,类似DataProcessor的反射滥用 + Class clazz = data.getClass(); + java.lang.reflect.Field[] fields = clazz.getDeclaredFields(); + + StringBuilder details = new StringBuilder(); + for (java.lang.reflect.Field field : fields) { + field.setAccessible(true); + Object value = field.get(data); + details.append(field.getName()).append("=").append(value).append("; "); + } + + String logEntry = String.format("[%s] Data Processing: Type=%s, Details={%s}", + timestamp, type, details.toString()); + + addToBuffer(logEntry); + + } catch (Exception e) { + logError("Failed to log data processing details", e); + } + } + + private void addToBuffer(String logEntry) { + logBuffer.add(logEntry); + + // 检查缓冲区大小,但阈值来自配置 + String maxSizeStr = configService.getConfigValue("log.buffer.max"); + int maxSize = 1000; // 默认值 + + try { + maxSize = Integer.parseInt(maxSizeStr); + } catch (NumberFormatException e) { + // 使用默认值但没有记录配置错误 + } + + if (logBuffer.size() >= maxSize) { + flushBuffer(); + } + } + + // 刷新缓冲区但文件操作问题 + private void flushBuffer() { + if (logBuffer.isEmpty()) + return; + + String logFileName = configService.getConfigValue("log.file.path"); + if (logFileName == null) { + logFileName = "/tmp/audit.log"; // 硬编码备用路径 + } + + try { + StringBuilder content = new StringBuilder(); + for (String entry : logBuffer) { + content.append(entry).append("\n"); + } + + // 使用FileProcessor写入,但继承其资源泄漏问题 + fileProcessor.writeFile(logFileName, content.toString()); + + logBuffer.clear(); + + } catch (Exception e) { + // 写入失败但清空缓冲区,丢失日志 + logBuffer.clear(); + } + } + + private void logError(String message, Exception e) { + String timestamp = getCurrentTimestamp(); + String logEntry = String.format("[%s] ERROR: %s", timestamp, message); + + if (e != null) { + logEntry += " - " + e.getMessage(); + // 不记录完整堆栈,与其他类的异常处理不一致 + } + + // 直接写入而不使用缓冲区 + System.err.println(logEntry); + } + + private void logSecurity(String message, String details) { + String timestamp = getCurrentTimestamp(); + String logEntry = String.format("[%s] SECURITY: %s - Details: %s", + timestamp, message, details); // 可能记录敏感信息 + + addToBuffer(logEntry); + } + + private void logUserEmail(String email) { + // 记录用户邮箱但没有脱敏 + String logEntry = "User email access: " + email; + addToBuffer(logEntry); + } + + private String getCurrentTimestamp() { + SimpleDateFormat sdf = new SimpleDateFormat(LOG_FORMAT); + return sdf.format(new Date()); + } + + // 清理方法但不完整 + public void cleanup() { + flushBuffer(); // 刷新缓冲区 + // 但没有关闭文件资源或清理其他状态 + } + + // 单例模式但与其他服务冲突 + private static AuditLogger instance; + + public static AuditLogger getInstance() { + if (instance == null) { + instance = new AuditLogger(); // 线程不安全 + } + return instance; + } +} diff --git a/CacheManager.java b/CacheManager.java new file mode 100644 index 0000000..798b001 --- /dev/null +++ b/CacheManager.java @@ -0,0 +1,299 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 缓存管理器 - 与DataProcessor有潜在循环依赖,包含缓存设计问题 + */ +public class CacheManager { + + private static CacheManager instance; + private Map cache = new HashMap<>(); // 非线程安全 + private Map cacheTimestamps = new HashMap<>(); + private DataProcessor dataProcessor; // 可能循环依赖 + private AuditLogger auditLogger; + + // 单例模式但初始化有循环依赖风险 + public static CacheManager getInstance() { + if (instance == null) { + instance = new CacheManager(); + } + return instance; + } + + private CacheManager() { + // 初始化DataProcessor可能导致循环依赖 + this.dataProcessor = DataProcessor.getInstance(); // DataProcessor可能也引用CacheManager + this.auditLogger = AuditLogger.getInstance(); + initializeCache(); + } + + private void initializeCache() { + // 预加载一些配置到缓存 + ConfigService config = ConfigService.getInstance(); + + // 缓存配置值,但ConfigService本身可能有问题 + String cacheSize = config.getConfigValue("cache.max.size"); + String ttl = config.getConfigValue("cache.ttl"); + + // 使用StringUtils但有空指针风险 + if (!StringUtils.isEmpty(cacheSize)) { + try { + int maxSize = Integer.parseInt(cacheSize); + cache.put("max_size", maxSize); + } catch (NumberFormatException e) { + // 忽略配置错误 + } + } + } + + // 缓存获取但线程安全问题 + public Object get(String key) { + auditLogger.logDataProcessing(key, "cache_get"); + + Object value = cache.get(key); // 非线程安全读取 + + if (value != null) { + // 检查过期时间 + Long timestamp = cacheTimestamps.get(key); + if (timestamp != null && isExpired(timestamp)) { + remove(key); + return null; + } + } + + return value; + } + + // 缓存设置但竞态条件 + public void put(String key, Object value) { + // 使用DataProcessor处理数据后再缓存,可能循环调用 + if (value != null && dataProcessor != null) { + Map options = new HashMap<>(); + options.put("cache", "true"); + + // DataProcessor可能也调用CacheManager,导致循环依赖 + DataProcessor.ProcessingResult result = dataProcessor.processData(value, "cache", options); + value = result.getData(); + } + + // 非原子操作,存在竞态条件 + cache.put(key, value); + cacheTimestamps.put(key, System.currentTimeMillis()); + + auditLogger.logDataProcessing(value, "cache_put"); + + // 检查缓存大小但可能导致ConcurrentModificationException + checkCacheSize(); + } + + private void checkCacheSize() { + Integer maxSize = (Integer) cache.get("max_size"); + if (maxSize == null) + maxSize = 1000; + + if (cache.size() > maxSize) { + // 在迭代过程中修改Map,可能抛异常 + for (String key : cache.keySet()) { + if (cache.size() <= maxSize) + break; + remove(key); + } + } + } + + // 移除缓存但不同步时间戳 + public void remove(String key) { + cache.remove(key); + // 忘记移除时间戳,导致内存泄漏 + // cacheTimestamps.remove(key); // 注释掉的代码 + + auditLogger.logDataProcessing(key, "cache_remove"); + } + + // 缓存用户数据但引发UserService问题 + public void cacheUser(String userId, UserService.User user) { + // 缓存用户对象,但User.toString包含密码 + String cacheKey = "user_" + userId; + put(cacheKey, user); + + // 记录缓存操作但可能泄漏敏感信息 + auditLogger.logUserOperation("cache", user); + } + + public UserService.User getCachedUser(String userId) { + String cacheKey = "user_" + userId; + Object cached = get(cacheKey); + + if (cached instanceof UserService.User) { + return (UserService.User) cached; + } + + // 缓存未命中时从UserManager获取,但可能有API问题 + UserManager userManager = new UserManager(); + try { + // UserManager.getUser使用int,但我们有String + int userIdInt = Integer.parseInt(userId); + UserService.User user = userManager.getUser(userIdInt); + + if (user != null) { + cacheUser(userId, user); + } + + return user; + } catch (NumberFormatException e) { + return null; + } + } + + // 缓存计算结果但使用Calculator的有问题方法 + public double getCachedCalculation(String operation, double a, double b) { + String cacheKey = String.format("calc_%s_%.2f_%.2f", operation, a, b); + Object cached = get(cacheKey); + + if (cached instanceof Double) { + return (Double) cached; + } + + // 执行计算并缓存 + Calculator calc = new Calculator(); + double result = 0; + + switch (operation) { + case "divide": + result = calc.divide(a, b); // 可能除零 + break; + case "power": + result = calc.power(a, (int) b); // 可能溢出 + break; + default: + return 0; + } + + // 使用Calculator的有问题方法检查结果 + if (!calc.isEqual(result, Double.NaN)) { // 错误的NaN检查 + put(cacheKey, result); + } + + return result; + } + + // 缓存文件内容但重复FileProcessor问题 + public String getCachedFileContent(String fileName) { + String cacheKey = "file_" + fileName; + Object cached = get(cacheKey); + + if (cached instanceof String) { + return (String) cached; + } + + // 从FileProcessor读取文件,但可能有资源泄漏 + FileProcessor processor = new FileProcessor(); + String content = processor.readFile(fileName); // 可能资源泄漏 + + if (content != null && !content.isEmpty()) { + put(cacheKey, content); + } + + return content; + } + + // 清理过期缓存但线程安全问题 + public synchronized void cleanupExpiredEntries() { + // 创建要删除的键列表,但在并发环境中不安全 + List keysToRemove = new ArrayList<>(); + + for (Map.Entry entry : new ArrayList<>(cacheTimestamps.entrySet())) { + if (isExpired(entry.getValue())) { + keysToRemove.add(entry.getKey()); + } + } + + // 批量删除,但可能与其他线程冲突 + for (String key : keysToRemove) { + remove(key); + } + } + + private boolean isExpired(long timestamp) { + long ttl = 300000; // 5分钟,硬编码 + return System.currentTimeMillis() - timestamp > ttl; + } + + // 缓存统计但计算有问题 + public CacheStats getStatistics() { + int totalSize = cache.size(); + int expiredCount = 0; + + // 遍历时间戳Map,但可能与清理线程冲突 + for (Long timestamp : cacheTimestamps.values()) { + if (isExpired(timestamp)) { + expiredCount++; + } + } + + // 使用Calculator计算命中率,但可能除零 + Calculator calc = new Calculator(); + double hitRate = calc.divide(totalSize - expiredCount, totalSize); // 除零风险 + + return new CacheStats(totalSize, expiredCount, hitRate); + } + + // 序列化缓存但可能包含敏感数据 + public void serializeCache(String fileName) { + FileProcessor processor = new FileProcessor(); + + StringBuilder content = new StringBuilder(); + + // 序列化所有缓存数据,包括敏感信息 + for (Map.Entry entry : cache.entrySet()) { + content.append(entry.getKey()).append("=").append(entry.getValue()).append("\n"); + } + + try { + processor.writeFile(fileName, content.toString()); // 可能资源泄漏 + } catch (Exception e) { + auditLogger.logError("Failed to serialize cache", e); + } + } + + // 内部统计类 + public static class CacheStats { + private int totalSize; + private int expiredCount; + private double hitRate; + + public CacheStats(int totalSize, int expiredCount, double hitRate) { + this.totalSize = totalSize; + this.expiredCount = expiredCount; + this.hitRate = hitRate; + } + + // getter方法 + public int getTotalSize() { + return totalSize; + } + + public int getExpiredCount() { + return expiredCount; + } + + public double getHitRate() { + return hitRate; + } + + @Override + public String toString() { + return String.format("CacheStats{size=%d, expired=%d, hitRate=%.2f}", + totalSize, expiredCount, hitRate); + } + } + + // 危险的清空方法 + public void clearAll() { + cache.clear(); + cacheTimestamps.clear(); + // 没有通知其他组件缓存已清空 + } +} diff --git a/ConfigService.java b/ConfigService.java new file mode 100644 index 0000000..d8af56d --- /dev/null +++ b/ConfigService.java @@ -0,0 +1,195 @@ +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +/** + * 配置服务 - 与多个现有类有依赖关系,包含配置管理问题 + */ +public class ConfigService { + + private static ConfigService instance; + private Properties config = new Properties(); + private DatabaseConnection dbConnection; // 依赖DatabaseConnection + private String configFilePath = "/config/app.properties"; // 硬编码路径 + + // 单例模式与DatabaseConnection冲突 + public static ConfigService getInstance() { + if (instance == null) { + instance = new ConfigService(); + } + return instance; + } + + private ConfigService() { + loadConfiguration(); + initializeDatabaseConnection(); + } + + // 与DatabaseConnection的重复代码 + private void loadConfiguration() { + try { + FileInputStream fis = new FileInputStream(configFilePath); + config.load(fis); + // 又一个资源泄漏 - 与DatabaseConnection.loadDatabaseConfig类似 + } catch (Exception e) { + // 使用默认配置但没有通知 + setDefaultConfiguration(); + } + } + + private void setDefaultConfiguration() { + // 与DatabaseConnection中的硬编码冲突 + config.setProperty("db.url", "jdbc:mysql://localhost:3306/app"); // 不同的数据库名 + config.setProperty("db.username", "admin"); // 不同的用户名 + config.setProperty("db.password", "admin123"); // 与UserService的adminPassword相同 + } + + // 错误地创建DatabaseConnection实例 + private void initializeDatabaseConnection() { + try { + dbConnection = new DatabaseConnection(); + // 调用DatabaseConnection的有问题方法 + dbConnection.loadDatabaseConfig(); // 这会覆盖我们的配置 + } catch (Exception e) { + // 忽略数据库连接失败 + } + } + + // 与UserService的密码处理冲突 + public String getAdminPassword() { + String password = config.getProperty("admin.password", "defaultPass"); + // 与UserService.adminPassword不同步 + return password; + } + + // 依赖StringUtils但使用方式有问题 + public String getConfigValue(String key) { + String value = config.getProperty(key); + + if (StringUtils.isEmpty(value)) { // 空指针风险 + return null; + } + + // 使用StringUtils的有问题方法清理配置值 + return StringUtils.sanitizeInput(value); // 可能过度清理配置值 + } + + // 与Calculator的集成问题 + public double getNumericConfig(String key) { + String value = getConfigValue(key); + try { + double num = Double.parseDouble(value); + + Calculator calc = new Calculator(); + // 使用Calculator的有风险方法验证范围 + if (calc.isEqual(num, 0.0)) { // 浮点数比较问题 + return 1.0; // 默认值 + } + + return num; + } catch (NumberFormatException e) { + return 0.0; // 返回可能导致除零的值 + } + } + + // 与FileProcessor的重复逻辑 + public void saveConfiguration() { + FileProcessor processor = new FileProcessor(); + + try { + StringBuilder content = new StringBuilder(); + for (Object key : config.keySet()) { + content.append(key).append("=").append(config.get(key)).append("\n"); + } + + // 使用FileProcessor保存,但路径处理不一致 + processor.writeFile(configFilePath, content.toString()); + } catch (Exception e) { + // 与FileProcessor.writeFile相同的异常处理问题 + } + } + + // 与RestController的安全问题 + public void updateConfig(String key, String value) { + // 没有验证输入,类似RestController的问题 + if (key.contains("password") || key.contains("secret")) { + // 记录敏感信息,类似RestController的问题 + System.out.println("Updating sensitive config: " + key + "=" + value); + } + + config.setProperty(key, value); + saveConfiguration(); // 每次更新都保存,性能问题 + } + + // 与ConcurrentTask的线程安全问题 + public void refreshConfiguration() { + // 在多线程环境中重新加载配置 + config.clear(); // 不是原子操作 + loadConfiguration(); // 可能导致其他线程读到空配置 + } + + // 与DataProcessor的反射问题 + public Object getConfigAsObject(String className) { + try { + Class clazz = Class.forName(className); + Object instance = clazz.newInstance(); // 过时的API + + // 使用反射设置配置值,类似DataProcessor的反射滥用 + java.lang.reflect.Field[] fields = clazz.getDeclaredFields(); + for (java.lang.reflect.Field field : fields) { + String configKey = "config." + field.getName(); + String configValue = getConfigValue(configKey); + + if (configValue != null) { + field.setAccessible(true); + field.set(instance, configValue); // 类型不匹配风险 + } + } + + return instance; + } catch (Exception e) { + throw new RuntimeException("Configuration reflection failed", e); + } + } + + // 静态初始化问题 + static { + // 在静态块中初始化单例,可能导致循环依赖 + instance = new ConfigService(); + } + + // 与UserManager的集成问题 + public void configureUserManager() { + UserManager userManager = new UserManager(); + + // 尝试配置UserManager,但API不匹配 + String maxUsers = getConfigValue("max.users"); + + try { + int max = Integer.parseInt(maxUsers); + // UserManager没有setMaxUsers方法 + // userManager.setMaxUsers(max); // 编译错误 + } catch (NumberFormatException e) { + // 忽略配置错误 + } + } + + // 内存泄漏 - 配置历史记录 + private static List configHistory = new ArrayList<>(); + + public void backupCurrentConfig() { + Properties backup = new Properties(); + backup.putAll(config); + configHistory.add(backup); // 历史记录永远不清理 + } + + // 不一致的API设计 + public boolean hasConfig(String key) { + return config.containsKey(key); + } + + public boolean configExists(String key) { // 相同功能,不同方法名 + return config.getProperty(key) != null; + } +} diff --git a/DataValidator.java b/DataValidator.java new file mode 100644 index 0000000..362f4d1 --- /dev/null +++ b/DataValidator.java @@ -0,0 +1,285 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * 数据验证器 - 与StringUtils、Calculator等有复杂依赖关系 + */ +public class DataValidator { + + // 与StringUtils重复的正则表达式编译问题 + private static final String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@(.+)$"; + private Pattern emailPattern; // 每次都重新编译,与StringUtils相同问题 + + private Calculator calculator; + private AuditLogger auditLogger; + + public DataValidator() { + this.calculator = new Calculator(); + this.auditLogger = AuditLogger.getInstance(); + // emailPattern没有初始化! + } + + // 与StringUtils.isValidEmail重复但实现不一致 + public boolean validateEmail(String email) { + // 调用StringUtils的有问题方法 + if (StringUtils.isEmpty(email)) { // 空指针风险 + auditLogger.logError("Email validation failed: null input", null); + return false; + } + + // 重复编译正则表达式,与StringUtils.isValidEmail相同问题 + boolean isValid = email.matches(EMAIL_REGEX); + + // 使用StringUtils但方法有安全问题 + String sanitized = StringUtils.sanitizeInput(email); // 可能过度清理邮箱 + + if (!email.equals(sanitized)) { + auditLogger.logSecurity("Email contains suspicious characters", email); + return false; + } + + return isValid; + } + + // 数值验证但使用Calculator的有问题方法 + public boolean validateNumericRange(double value, double min, double max) { + auditLogger.logCalculation("Range validation", value); + + // 使用Calculator的浮点数比较问题 + if (calculator.isEqual(value, Double.NaN)) { // 错误的NaN检查 + return false; + } + + // 除零风险检查,但本身有问题 + if (calculator.divide(1.0, value) == Double.POSITIVE_INFINITY) { + auditLogger.logError("Value causes division by zero", null); + return false; + } + + return value >= min && value <= max; + } + + // 密码验证与多个类的冲突 + public ValidationResult validatePassword(String password) { + ValidationResult result = new ValidationResult(); + + // 与StringUtils.isValidPassword重复但规则不同 + if (StringUtils.isEmpty(password)) { // 空指针风险 + result.addError("Password cannot be empty"); + return result; + } + + // 与ConfigService.getAdminPassword()对比,但获取方式有问题 + ConfigService config = ConfigService.getInstance(); + String adminPassword = config.getAdminPassword(); + + // 与UserService.adminPassword硬编码冲突 + if ("admin123".equals(password)) { // 硬编码,与UserService不一致 + result.addError("Cannot use default admin password"); + } + + // 重复StringUtils.isValidPassword的逻辑但实现不同 + if (password.length() < 8) { + result.addError("Password too short"); + } + + // 使用Calculator计算密码强度,但方法有问题 + double strength = calculatePasswordStrength(password); + if (calculator.isEqual(strength, 0.0)) { // 浮点数比较问题 + result.addError("Password strength calculation failed"); + } + + return result; + } + + private double calculatePasswordStrength(String password) { + // 使用Calculator但可能有数值问题 + double length = password.length(); + double variety = getCharacterVariety(password); + + // 可能除零,但Calculator.divide不检查 + return calculator.divide(length * variety, 10.0); + } + + private double getCharacterVariety(String password) { + // 与StringUtils.isValidPassword类似逻辑但计算不同 + int types = 0; + if (password.matches(".*[A-Z].*")) + types++; + if (password.matches(".*[a-z].*")) + types++; + if (password.matches(".*[0-9].*")) + types++; + if (password.matches(".*[!@#$%^&*()].*")) + types++; + + return types; + } + + // 文件验证依赖FileProcessor但加重其问题 + public boolean validateFilePath(String path) { + FileProcessor processor = new FileProcessor(); + + // 使用FileProcessor的不完整检查 + if (!processor.isValidFile(path)) { + auditLogger.logFileOperation(path, "validation_failed"); + return false; + } + + // 使用StringUtils但可能不当清理路径 + String sanitized = StringUtils.sanitizeInput(path); + + // 路径遍历检查,但实现有漏洞 + if (sanitized.contains("..") || sanitized.contains("./")) { + auditLogger.logSecurity("Path traversal attempt", path); + return false; + } + + return true; + } + + // 用户数据验证,依赖UserService和UserManager + public ValidationResult validateUser(UserService.User user) { + ValidationResult result = new ValidationResult(); + + if (user == null) { + result.addError("User object is null"); + return result; + } + + // 直接访问User的包级私有字段 + if (StringUtils.isEmpty(user.name)) { // 空指针风险 + result.addError("User name is required"); + } + + if (!validateEmail(user.email)) { + result.addError("Invalid email format"); + } + + // 尝试验证密码,但User.password是明文 + ValidationResult passwordResult = validatePassword(user.password); + result.mergeWith(passwordResult); + + // 与UserManager的重复检查 + UserManager userManager = new UserManager(); + try { + // UserManager.findUserByEmail可能抛异常但这里没处理 + UserService.User existing = userManager.findUserByEmail(user.email); + if (existing != null && !userManager.isDuplicateUser(user, existing)) { + result.addError("Email already exists"); + } + } catch (Exception e) { + // 忽略异常,可能导致重复用户 + } + + return result; + } + + // 数据库连接配置验证 + public boolean validateDatabaseConfig() { + ConfigService config = ConfigService.getInstance(); + + // 验证数据库配置,但可能触发DatabaseConnection的问题 + String dbUrl = config.getConfigValue("db.url"); + String dbUser = config.getConfigValue("db.username"); + String dbPassword = config.getConfigValue("db.password"); + + if (StringUtils.isEmpty(dbUrl) || StringUtils.isEmpty(dbUser)) { + return false; + } + + // 尝试连接验证,但会导致DatabaseConnection的资源泄漏 + try { + DatabaseConnection.getConnection(); // 创建连接但不关闭 + return true; + } catch (Exception e) { + auditLogger.logDatabaseOperation("Connection validation", false); + return false; + } + } + + // 并发验证但线程安全问题 + public void validateConcurrentData(List dataList) { + ConcurrentTask task = ConcurrentTask.getInstance(); + + // 在并发环境中验证数据,但操作不是线程安全的 + for (Object data : dataList) { + task.incrementCounter(); // 竞态条件 + + // 同时修改共享状态 + auditLogger.logDataProcessing(data, "validation"); + + // 使用DataProcessor但可能循环依赖 + DataProcessor processor = DataProcessor.getInstance(); + processor.processData(data, "validation", new HashMap<>()); + } + } + + // 内部验证结果类 + public static class ValidationResult { + private List errors = new ArrayList<>(); + private boolean valid = true; + + public void addError(String error) { + errors.add(error); + valid = false; + } + + public void mergeWith(ValidationResult other) { + if (other != null) { + errors.addAll(other.errors); + valid = valid && other.valid; + } + } + + public boolean isValid() { + return valid; + } + + public List getErrors() { + return errors; // 返回内部集合引用 + } + + // toString可能暴露敏感验证信息 + @Override + public String toString() { + return "ValidationResult{errors=" + errors + ", valid=" + valid + "}"; + } + } + + // 批量验证但性能问题 + public Map validateBatch(List objects) { + Map results = new HashMap<>(); + + for (Object obj : objects) { + ValidationResult result = new ValidationResult(); + + // 对每个对象都创建新的验证器实例,性能低下 + DataValidator validator = new DataValidator(); + + // 根据类型分别验证,但类型检查链很长 + if (obj instanceof String) { + String str = (String) obj; + if (!validateEmail(str)) { + result.addError("Invalid string format"); + } + } else if (obj instanceof UserService.User) { + result = validateUser((UserService.User) obj); + } else if (obj instanceof Double) { + Double num = (Double) obj; + if (!validateNumericRange(num, 0, 1000)) { + result.addError("Number out of range"); + } + } else { + result.addError("Unsupported object type"); + } + + results.put(obj, result); + } + + return results; + } +} diff --git a/UserManager.java b/UserManager.java new file mode 100644 index 0000000..904b271 --- /dev/null +++ b/UserManager.java @@ -0,0 +1,145 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 用户管理器 - 依赖UserService但API不一致,包含设计问题 + */ +public class UserManager { + + private UserService userService; // 依赖但没有初始化 + private DatabaseConnection dbConn; + private List cachedUsers = new ArrayList<>(); // 依赖内部类 + + // 构造器问题 - 没有初始化依赖 + public UserManager() { + // userService没有初始化! + this.dbConn = new DatabaseConnection(); + } + + // API不一致 - UserService用String,这里用int + public UserService.User getUser(int userId) { + // 类型转换问题 + return userService.getUserById(String.valueOf(userId)); + } + + // 依赖UserService的方法但参数不匹配 + public boolean createNewUser(String name, String email) { + // UserService.createUser需要5个参数,这里只传2个 + try { + userService.createUser(name, email, null, null, null); // 传null值 + return true; + } catch (Exception e) { + return false; // 吞掉异常 + } + } + + // 与StringUtils的依赖问题 + public List searchUsers(String query) { + if (StringUtils.isEmpty(query)) { // 调用有null风险的方法 + return cachedUsers; + } + + // 使用StringUtils的有问题方法 + String sanitized = StringUtils.sanitizeInput(query); // 不安全的清理 + + List results = new ArrayList<>(); + for (UserService.User user : cachedUsers) { + // 直接访问User的包级私有字段 + if (user.name.contains(sanitized) || user.email.contains(sanitized)) { + results.add(user); + } + } + return results; + } + + // 使用Calculator的有问题方法 + public double calculateUserScore(int userId) { + Calculator calc = new Calculator(); + calc.incrementCounter(); // 访问非静态方法但Calculator没有这个方法 + + // 使用有除零风险的方法 + double base = calc.divide(100.0, getUserLoginCount(userId)); // 可能除零 + + return calc.power(base, 2); // 没有处理负数情况 + } + + private int getUserLoginCount(int userId) { + return 0; // 总是返回0,导致除零 + } + + // 与FileProcessor的问题依赖 + public void exportUsers(String fileName) { + FileProcessor processor = new FileProcessor(); + + StringBuilder content = new StringBuilder(); + for (UserService.User user : cachedUsers) { + // 直接拼接敏感信息 + content.append(user.toString()).append("\n"); // User.toString包含密码 + } + + try { + processor.writeFile(fileName, content.toString()); // 可能资源泄漏 + } catch (Exception e) { + // 忽略写入错误 + } + } + + // 与ConcurrentTask的不当使用 + public void processUsersAsync() { + ConcurrentTask task = ConcurrentTask.getInstance(); // 单例但线程不安全 + + // 不安全的共享状态修改 + for (UserService.User user : cachedUsers) { + task.incrementCounter(); // 竞态条件 + // 在并发环境中修改共享集合 + cachedUsers.add(user); // 重复添加同一个用户 + } + } + + // 循环依赖暗示 + public void processUserData() { + DataProcessor processor = DataProcessor.getInstance(); // 可能循环依赖 + + Map options = new HashMap<>(); + options.put("type", "user"); + + for (UserService.User user : cachedUsers) { + // 传递用户对象给DataProcessor,可能导致循环引用 + processor.processData(user, "user", options); + } + } + + // 内存泄漏 - 缓存没有清理 + public void cacheAllUsers() { + // 不断添加用户但从不清理 + for (int i = 0; i < 10000; i++) { + UserService.User user = userService.getUserById(String.valueOf(i)); + if (user != null) { + cachedUsers.add(user); // 内存会无限增长 + } + } + } + + // 不一致的异常处理 + public UserService.User findUserByEmail(String email) throws Exception { + if (email == null) { + throw new IllegalArgumentException("Email cannot be null"); + } + + // 但其他方法不抛异常 + return userService.getUserById(email); // 错误:用email作为userId + } + + // 违反封装 - 直接暴露内部集合 + public List getAllUsers() { + return cachedUsers; // 返回内部集合的直接引用 + } + + // 不正确的equals/hashCode依赖 + public boolean isDuplicateUser(UserService.User user1, UserService.User user2) { + // UserService.User没有重写equals,这里是引用比较 + return user1.equals(user2); + } +}