Building a Community Epidemic Prevention and Control Platform with Spring Boot and Vue.js
Technical Architecture
The backend service is powered by the Spring Boot framework. This framework leverages an embedded Tomcat container, removing the need for manual WAR file deployment. Its auto-configuration mechanism adapts application settings based on detected classpath dependencies, significantly reducing manual XML configuration. The ecosystem supports various production-ready tools, including Spring Security and data integration modules, to ensure robust application delivery.
The frontend is constructed using Vue.js. The library employs a Virtual DOM strategy to optimize rendering performance by minimizing actual DOM manipulation. Its reactive data binding model ensures the view layer stays synchronized with the underlying data state, allowing developers to prioritize business logic over UI manipulation.
Persistence is handled via MyBatis-Plus. This enhancement tool extends standard MyBatis capabilities by providing powerful CRUD wrappers. It integrates features such as pagination plugins and dynamic SQL builders, facilitating rapid and secure access to databases like MySQL.
System Testing and Validation
The testing strategy primarily employs black-box techniques to verify that system behavior meets requirements without inspecting internal code structures.
Functional Verification
Authentication Module: Test cases verify that access is granted when valid credentials are submitted. The system also confirms that logic correctly rejects invalid passwords, incorrect CAPTCHA inputs, and empty username fields. Scenarios also check for the presence of specific role validation logic within the database.
User Management: This module underwent testing against Create, Read, Update, and Delete (CRUD) operations. The validation process ensures the system enforces non-null constraints when mandatory fields are missing. Additionally, the system checks for uniqueness constraints (rejecting duplicate usernames) and verifies that deletion operations permanently remove records from both the view and data store.
Implementation Code Examples
Authentication Controller
The following controller handles authentication requests, validating credentials and generating a session token.
@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {
@Autowired
private UserService userService;
@Autowired
private TokenManager tokenManager;
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> authenticate(@RequestBody CredentialsDto credentials, HttpServletRequest request) {
UserProfile user = userService.retrieveByUsername(credentials.getUsername());
if (user == null || !userService.validatePassword(user, credentials.getPassword())) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Map.of("status", "error", "message", "Invalid username or password"));
}
String authToken = tokenManager.issueToken(user.getId(), user.getUsername(), user.getRole());
return ResponseEntity.ok(Map.of("status", "success", "token", authToken));
}
}
Token Generation Service
This service generates secure random tokens and manages them with an expiration time.
@Service
public class TokenManager {
@Autowired
private SessionRepository sessionRepository;
public String issueToken(Long userId, String username, String role) {
String rawToken = generateSecureString();
LocalDateTime expiration = LocalDateTime.now().plusHours(1);
SessionEntity existingSession = sessionRepository.findByUserId(userId);
if (existingSession != null) {
existingSession.setToken(rawToken);
existingSession.setExpiryDate(expiration);
sessionRepository.update(existingSession);
} else {
SessionEntity newSession = new SessionEntity(userId, username, role, rawToken, expiration);
sessionRepository.save(newSession);
}
return rawToken;
}
private String generateSecureString() {
// Implementation for generating a random 32-char string
return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
}
}
Security Interceptor
This interceptor ensures that requests to protected endpoints contain a valid authentication token.
@Component
public class SecurityInterceptor implements HandlerInterceptor {
public static final String AUTH_HEADER = "X-Auth-Token";
@Autowired
private TokenManager tokenManager;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Handle CORS preflight requests
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
if (!(handler instanceof HandlerMethod)) {
return true;
}
// Bypass authentication for methods annotated with PublicEndpoint
HandlerMethod method = (HandlerMethod) handler;
if (method.getMethodAnnotation(PublicEndpoint.class) != null) {
return true;
}
String clientToken = request.getHeader(AUTH_HEADER);
if (StringUtils.isNotBlank(clientToken) && tokenManager.validateToken(clientToken)) {
return true;
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/");
try {
response.getWriter().write("{\"error\":\"Unauthorized\"}");
} catch (IOException e) {
// Log error
}
return false;
}
}
Database Schema Reference
The following SQL script defines the table structure for storing user sessions and authentication tokens.
-- Drop existing table if it exists
DROP TABLE IF EXISTS `user_sessions`;
-- Create the session table
CREATE TABLE `user_sessions` (
`session_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`user_id` BIGINT(20) NOT NULL COMMENT 'Associated User ID',
`username` VARCHAR(100) NOT NULL COMMENT 'Username',
`role_name` VARCHAR(50) DEFAULT NULL COMMENT 'User Role',
`auth_token` VARCHAR(200) NOT NULL COMMENT 'Authentication Token',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
`expires_at` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Token Expiration',
PRIMARY KEY (`session_id`) USING BTREE,
INDEX `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='User Session Storage';