Graduate Credential Verification System: Architecture and Implementation with Spring Boot, Vue.js, and UniApp

Technology Stack

Backend Framework: Spring Boot

Spring Boot simplifies the development of production-ready applications by leveraging the Spring ecosystem. It eliminates the need for extensive XML configurations through its intelligent auto-configuration mechanism, which dynamically configures the application based on the detected classpath dependencies. Embedded HTTP servers like Tomcat or Undertow allow standalone execution without requiring external server deployments. Furthermore, its robust integration capabilities with data access layers, security modules, and cloud components enable the rapid construction of scalable and maintainable enterprise backend systems.

The following snippet demonstrates a basic endpoint setup:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@SpringBootApplication
@RestController
public class CredentialSystemApp {

    public static void main(String[] args) {
        SpringApplication.run(CredentialSystemApp.class, args);
    }

    @GetMapping("/api/system-status")
    public Map checkStatus() {
        return Map.of("status", "OPERATIONAL", "service", "CredentialVerification");
    }
}

Frontend Framework: Vue.js

Vue.js employs a reactive data-binding system combined with a component-based architecture, allowing developers to build interactive user interfaces efficiently. The framework utilizes a Virtual DOM to optimize rendering performance, ensuring that only the necessary components are re-rendered when the underlying state changes. This declarative approach abstracts manual DOM manipulations, streamlining the development of complex single-page applications.

Below is an illustrative example of Vue.js reactivity:

<div id="verify-app">
  <p>Verification Status: {{ statusText }}</p>
  <button @click="toggleStatus">Toggle Status</button>
</div>

<script>
  new Vue({
    el: '#verify-app',
    data: {
      isVerified: false
    },
    computed: {
      statusText: function() {
        return this.isVerified ? 'Authenticated' : 'Pending Review';
      }
    },
    methods: {
      toggleStatus: function() {
        this.isVerified = !this.isVerified;
      }
    }
  });
</script>

Persistence Layer: MyBatis

MyBatis provides a semi-automated ORM approach, offering fine-grained control over SQL queries while automating the mapping between database records and Java objects. It supports dynamic SQL generation, enabling developers to construct complex queries based on varying conditions without string concatenation. Its plugin architecture and caching mechanisms further enhance performance and extensibility, making it suitable for applications requiring optimized database interactions.

Core Implementation Logic

Authentication and Token Management

The system implements a token-based authentication mechanism. Upon successful validation of credentials, a signed token is generated and returned to the client. Subsequent requests must include this token in the HTTP header, which is then validated by a server-side interceptor.

// Controller for user authentication
@SkipAuthVerification
@PostMapping(value = "/api/authenticate")
public ResponseEntity<?> authenticateUser(String account, String secret, String captcha) {
   AccountEntity accountEntity = accountService.retrieveByUsername(account);
   if (accountEntity == null || !accountEntity.getSecret().equals(secret)) {
      return ResponseEntity.status(401).body(Map.of("error", "Invalid credentials"));
   }
   String accessToken = accessTokenManager.issueToken(accountEntity.getId(), accountEntity.getRole());
   return ResponseEntity.ok(Map.of("accessToken", accessToken));
}

// Token generation logic
public String issueToken(Long accountId, String role) {
   AccessToken existingToken = this.findTokenByAccountAndRole(accountId, role);
   String tokenValue = SecureRandomUtil.generateAlphaNumeric(40);
   Instant expiryTime = Instant.now().plus(Duration.ofHours(2));
   
   if (existingToken != null) {
      existingToken.setValue(tokenValue);
      existingToken.setExpiry(expiryTime);
      this.updateRecord(existingToken);
   } else {
      AccessToken newToken = new AccessToken(accountId, role, tokenValue, expiryTime);
      this.insertRecord(newToken);
   }
   return tokenValue;
}

API Security Interceptor

The interceptor validates incoming requests for a valid access token, except for endpoints annotated with @SkipAuthVerification. It also handles Cross-Origin Resource Sharing (CORS) configurations.

@Component
public class ApiSecurityFilter implements HandlerInterceptor {

    public static final String AUTH_HEADER = "Authorization";

    @Autowired
    private AccessTokenManager accessTokenManager;
    
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
        res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
        res.setHeader("Access-Control-Allow-Credentials", "true");
        res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");

        if ("OPTIONS".equalsIgnoreCase(req.getMethod())) {
            res.setStatus(HttpServletResponse.SC_OK);
            return false;
        }

        SkipAuthVerification skipAnnotation = null;
        if (handler instanceof HandlerMethod) {
            skipAnnotation = ((HandlerMethod) handler).getMethodAnnotation(SkipAuthVerification.class);
        }

        if (skipAnnotation != null) {
            return true;
        }

        String headerToken = req.getHeader(AUTH_HEADER);
        AccessToken tokenRecord = StringUtils.isNotBlank(headerToken) ? accessTokenManager.validateToken(headerToken) : null;

        if (tokenRecord != null) {
            req.setAttribute("currentAccountId", tokenRecord.getAccountId());
            req.setAttribute("currentRole", tokenRecord.getRole());
            return true;
        }

        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        res.setContentType("application/;charset=UTF-8");
        res.getWriter().write("{\"error\": \"Authentication required\"}");
        return false;
    }
}

Database Schema Design

For credential verification, the system utilizes structured relational tables. Below is an example of an academic credential table:

CREATE TABLE `academic_credential` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
  `student_name` varchar(100) NOT NULL COMMENT 'Student Full Name',
  `degree_level` varchar(50) NOT NULL COMMENT 'Degree Level',
  `major` varchar(100) NOT NULL COMMENT 'Major Subject',
  `institution` varchar(150) NOT NULL COMMENT 'Issuing Institution',
  `issue_date` date NOT NULL COMMENT 'Date of Issuance',
  `is_revoked` tinyint(1) DEFAULT 0 COMMENT 'Revocation Status',
  `created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Academic Credentials';

INSERT INTO `academic_credential` (`student_name`, `degree_level`, `major`, `institution`, `issue_date`)
VALUES ('Alice Smith', 'Bachelor', 'Computer Science', 'Tech University', '2023-06-15');

INSERT INTO `academic_credential` (`student_name`, `degree_level`, `major`, `institution`, `issue_date`)
VALUES ('Bob Johnson', 'Master', 'Data Science', 'Institute of Technology', '2023-08-20');

System Quality Assurance

Comprehensive testing is conducted to ensure system reliability and functional correctness. This involves black-box testing methodologies to validate that all modules behave according to the specified requirements without logical flaws.

Authentication Functionality Tests

Test InputExpected OutcomeActual OutcomeStatus
Account: admin, Secret: pass123, Captcha: validSuccessful login, token returnedToken successfully generatedPass
Account: admin, Secret: wrongpass, Captcha: validAuthentication failedInvalid credentials error displayedPass
Account: admin, Secret: pass123, Captcha: invalidCaptcha validation failedCaptcha mismatch error displayedPass
Account: [empty], Secret: pass123, Captcha: validValidation errorAccount required error displayedPass

Account Management Functionality Tests

Account Creation Tests

Test InputExpected OutcomeActual OutcomeStatus
Account: userA, Secret: 123456, Role: StandardAccount created successfullyAccount userA appears in listPass
Account: userB, Secret: 123456, Role: StandardAccount created successfullyAccount userB appears in listPass
Account: userA, Secret: 123456, Role: StandardDuplicate account errorUsername exists error displayedPass
Account: [empty], Secret: 123456, Role: StandardValidation errorAccount required error displayedPass

Account Modification Tests

Test InputExpected OutcomeActual OutcomeStatus
Modify userA secret to 654321Secret updated successfullyuserA secret changedPass
Modify userB role to AdministratorRole updated successfullyuserB role changedPass
Clear userA account nameValidation errorAccount required error displayedPass

Account Deletion Tests

Test InputExpected OutcomeActual OutcomeStatus
Delete userA, confirm deletionAccount removed from systemuserA successfully deletedPass
Delete userB, cancel deletionDeletion aborteduserB remains in systemPass

Tags: Spring Boot Vue.js UniApp MyBatis System Testing

Posted on Mon, 13 Jul 2026 16:39:26 +0000 by Richard