First backend commit //main focus on Auth and JWT service not available for now

Change-Id: Ifccbc53798588f91244e095d6072990ac9e0b9fa
diff --git a/backend/demo/Dockerfile b/backend/demo/Dockerfile
new file mode 100644
index 0000000..5d92360
--- /dev/null
+++ b/backend/demo/Dockerfile
@@ -0,0 +1,25 @@
+# 构建阶段:使用 Maven 构建项目
+FROM maven:3.9.9-eclipse-temurin-24-alpine AS builder
+
+WORKDIR /app
+
+# 复制项目文件(忽略 target 目录)
+COPY pom.xml .
+COPY src ./src
+
+# 构建应用,跳过测试
+RUN mvn clean package -DskipTests
+
+# 运行阶段:使用较小的 JDK 镜像运行应用
+FROM openjdk:17-jdk-slim-buster
+
+WORKDIR /app
+
+# 从构建阶段复制打好的 jar 包
+COPY --from=builder /app/target/demo-0.0.1-SNAPSHOT.jar app.jar
+
+# 暴露 Spring Boot 默认端口
+EXPOSE 8080
+
+# 启动命令
+CMD ["java", "-jar", "app.jar"]
diff --git a/backend/demo/compose.yaml b/backend/demo/compose.yaml
index 4d2047e..61d6b9d 100644
--- a/backend/demo/compose.yaml
+++ b/backend/demo/compose.yaml
@@ -1,10 +1,29 @@
+
 services:
   mysql:
-    image: 'mysql:latest'
+    image: mysql:latest
     environment:
-      - 'MYSQL_DATABASE=mydatabase'
-      - 'MYSQL_PASSWORD=secret'
-      - 'MYSQL_ROOT_PASSWORD=verysecret'
-      - 'MYSQL_USER=myuser'
+      - MYSQL_DATABASE=mydatabase
+      - MYSQL_USER=myuser
+      - MYSQL_PASSWORD=secret
+      - MYSQL_ROOT_PASSWORD=verysecret
     ports:
-      - '3306'
+      - "3306:3306"
+    volumes:
+      - mysql-data:/var/lib/mysql
+
+  app:
+    build:
+      context: .
+      dockerfile: Dockerfile
+    ports:
+      - "8080:8080"
+    environment:
+      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydatabase?serverTimezone=Asia/Shanghai
+      SPRING_DATASOURCE_USERNAME: myuser
+      SPRING_DATASOURCE_PASSWORD: secret
+    depends_on:
+      - mysql
+
+volumes:
+  mysql-data:
diff --git a/backend/demo/dependency_tree.txt b/backend/demo/dependency_tree.txt
new file mode 100644
index 0000000..7f66fd4
--- /dev/null
+++ b/backend/demo/dependency_tree.txt
@@ -0,0 +1,197 @@
+[INFO] Scanning for projects...
+[INFO] 
+[INFO] --------------------------< com.example:demo >--------------------------
+[INFO] Building demo 0.0.1-SNAPSHOT
+[INFO]   from pom.xml
+[INFO] --------------------------------[ jar ]---------------------------------
+[INFO] 
+[INFO] --- dependency:3.8.1:tree (default-cli) @ demo ---
+[INFO] com.example:demo:jar:0.0.1-SNAPSHOT
+[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:3.4.4:compile
+[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:3.4.4:compile (version managed from 3.4.4; scope not updated to compile)
+[INFO] |  |  +- (org.springframework.boot:spring-boot:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  |  +- (org.springframework.boot:spring-boot-autoconfigure:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:3.4.4:compile (version managed from 3.4.4)
+[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.5.18:compile (version managed from 1.5.18)
+[INFO] |  |  |  |  +- ch.qos.logback:logback-core:jar:1.5.18:compile (version managed from 1.5.18)
+[INFO] |  |  |  |  \- (org.slf4j:slf4j-api:jar:2.0.17:compile - version managed from 2.0.17; omitted for duplicate)
+[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.24.3:compile (version managed from 2.24.3)
+[INFO] |  |  |  |  +- org.apache.logging.log4j:log4j-api:jar:2.24.3:compile (version managed from 2.24.3)
+[INFO] |  |  |  |  \- (org.slf4j:slf4j-api:jar:2.0.17:compile - version managed from 2.0.16; omitted for duplicate)
+[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:2.0.17:compile (version managed from 2.0.17)
+[INFO] |  |  |     \- (org.slf4j:slf4j-api:jar:2.0.17:compile - version managed from 2.0.17; omitted for duplicate)
+[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile (version managed from 2.1.1)
+[INFO] |  |  +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  |  \- org.yaml:snakeyaml:jar:2.3:compile (version managed from 2.3)
+[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:3.4.4:compile (version managed from 3.4.4)
+[INFO] |  |  +- (org.springframework.boot:spring-boot-starter:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  |  +- (org.springframework:spring-web:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  |  +- (com.fasterxml.jackson.core:jackson-databind:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.18.3:compile (version managed from 2.18.3)
+[INFO] |  |  |  +- (com.fasterxml.jackson.core:jackson-core:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  |  |  \- (com.fasterxml.jackson.core:jackson-databind:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.18.3:compile (version managed from 2.18.3)
+[INFO] |  |  |  +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  |  |  +- (com.fasterxml.jackson.core:jackson-core:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  |  |  \- (com.fasterxml.jackson.core:jackson-databind:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  |  \- (com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.4.4:compile (version managed from 3.4.4)
+[INFO] |  |  +- (jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile - version managed from 2.1.1; omitted for duplicate)
+[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.39:compile (version managed from 10.1.39)
+[INFO] |  |  +- (org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.39:compile - version managed from 10.1.39; omitted for duplicate)
+[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.39:compile (version managed from 10.1.39)
+[INFO] |  |     \- (org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.39:compile - version managed from 10.1.39; omitted for duplicate)
+[INFO] |  +- org.springframework:spring-web:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |  |  +- org.springframework:spring-beans:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |  |  |  \- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  |  +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  |  \- io.micrometer:micrometer-observation:jar:1.14.5:compile (version managed from 1.14.5)
+[INFO] |  |     \- io.micrometer:micrometer-commons:jar:1.14.5:compile (version managed from 1.14.5)
+[INFO] |  \- org.springframework:spring-webmvc:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |     +- (org.springframework:spring-aop:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     +- org.springframework:spring-context:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |     |  +- (org.springframework:spring-aop:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     |  +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     |  +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     |  +- (org.springframework:spring-expression:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     |  \- (io.micrometer:micrometer-observation:jar:1.14.5:compile - version managed from 1.14.5; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     +- org.springframework:spring-expression:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |     |  \- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |     \- (org.springframework:spring-web:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] +- com.mysql:mysql-connector-j:jar:9.1.0:runtime
+[INFO] +- com.baomidou:mybatis-plus-spring-boot3-starter:jar:3.5.5:compile
+[INFO] |  +- com.baomidou:mybatis-plus:jar:3.5.5:compile
+[INFO] |  |  +- com.baomidou:mybatis-plus-core:jar:3.5.5:compile
+[INFO] |  |  |  +- (com.baomidou:mybatis-plus-annotation:jar:3.5.5:compile - omitted for duplicate)
+[INFO] |  |  |  +- (com.github.jsqlparser:jsqlparser:jar:4.6:compile - omitted for duplicate)
+[INFO] |  |  |  \- (org.mybatis:mybatis:jar:3.5.15:compile - omitted for duplicate)
+[INFO] |  |  +- com.baomidou:mybatis-plus-annotation:jar:3.5.5:compile
+[INFO] |  |  +- com.baomidou:mybatis-plus-extension:jar:3.5.5:compile
+[INFO] |  |  |  \- (com.baomidou:mybatis-plus-core:jar:3.5.5:compile - omitted for duplicate)
+[INFO] |  |  +- org.mybatis:mybatis:jar:3.5.15:compile
+[INFO] |  |  \- com.github.jsqlparser:jsqlparser:jar:4.6:compile
+[INFO] |  +- org.mybatis:mybatis-spring:jar:3.0.3:compile
+[INFO] |  +- com.baomidou:mybatis-plus-spring-boot-autoconfigure:jar:3.5.5:compile
+[INFO] |  +- org.springframework.boot:spring-boot-autoconfigure:jar:3.4.4:compile (version managed from 3.2.0; scope not updated to compile)
+[INFO] |  |  \- (org.springframework.boot:spring-boot:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  \- org.springframework.boot:spring-boot-starter-jdbc:jar:3.4.4:compile (version managed from 3.2.0)
+[INFO] |     +- (org.springframework.boot:spring-boot-starter:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |     +- com.zaxxer:HikariCP:jar:5.1.0:compile (version managed from 5.1.0)
+[INFO] |     |  \- (org.slf4j:slf4j-api:jar:2.0.17:compile - version managed from 1.7.36; omitted for duplicate)
+[INFO] |     \- org.springframework:spring-jdbc:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |        +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |        +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |        \- org.springframework:spring-tx:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |           +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |           \- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] +- org.springframework.boot:spring-boot-configuration-processor:jar:3.4.4:compile
+[INFO] +- org.springframework.boot:spring-boot-docker-compose:jar:3.4.4:runtime
+[INFO] |  +- org.springframework.boot:spring-boot:jar:3.4.4:compile (version managed from 3.4.4; scope not updated to compile)
+[INFO] |  |  +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  |  \- (org.springframework:spring-context:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.18.3:compile (version managed from 2.18.3; scope not updated to compile)
+[INFO] |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.18.3:compile (version managed from 2.18.3)
+[INFO] |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.18.3:compile (version managed from 2.18.3)
+[INFO] |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.18.3:compile (version managed from 2.18.3; scope not updated to compile)
+[INFO] |     +- (com.fasterxml.jackson.core:jackson-core:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] |     \- (com.fasterxml.jackson.core:jackson-databind:jar:2.18.3:compile - version managed from 2.18.3; omitted for duplicate)
+[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:3.4.4:test
+[INFO] |  +- (org.springframework.boot:spring-boot-starter:jar:3.4.4:test - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  +- org.springframework.boot:spring-boot-test:jar:3.4.4:test (version managed from 3.4.4)
+[INFO] |  |  +- (org.springframework.boot:spring-boot:jar:3.4.4:test - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  |  \- (org.springframework:spring-test:jar:6.2.5:test - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:3.4.4:test (version managed from 3.4.4)
+[INFO] |  |  +- (org.springframework.boot:spring-boot:jar:3.4.4:test - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  |  +- (org.springframework.boot:spring-boot-test:jar:3.4.4:test - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  |  \- (org.springframework.boot:spring-boot-autoconfigure:jar:3.4.4:test - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.9.0:test (version managed from 2.9.0)
+[INFO] |  |  +- (net.minidev:json-smart:jar:2.5.2:test - version managed from 2.5.0; omitted for duplicate)
+[INFO] |  |  \- org.slf4j:slf4j-api:jar:2.0.17:compile (version managed from 2.0.11)
+[INFO] |  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.2:test (version managed from 4.0.2)
+[INFO] |  |  \- jakarta.activation:jakarta.activation-api:jar:2.1.3:test (version managed from 2.1.3)
+[INFO] |  +- net.minidev:json-smart:jar:2.5.2:test (version managed from 2.5.2)
+[INFO] |  |  \- net.minidev:accessors-smart:jar:2.5.2:test
+[INFO] |  |     \- org.ow2.asm:asm:jar:9.7.1:test
+[INFO] |  +- org.assertj:assertj-core:jar:3.26.3:test (version managed from 3.26.3)
+[INFO] |  |  \- net.bytebuddy:byte-buddy:jar:1.15.11:test (version managed from 1.14.18)
+[INFO] |  +- org.awaitility:awaitility:jar:4.2.2:test (version managed from 4.2.2)
+[INFO] |  |  \- (org.hamcrest:hamcrest:jar:2.2:test - version managed from 2.1; omitted for duplicate)
+[INFO] |  +- org.hamcrest:hamcrest:jar:2.2:test (version managed from 2.2)
+[INFO] |  +- org.junit.jupiter:junit-jupiter:jar:5.11.4:test (version managed from 5.11.4)
+[INFO] |  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.11.4:test (version managed from 5.11.4)
+[INFO] |  |  |  +- org.opentest4j:opentest4j:jar:1.3.0:test
+[INFO] |  |  |  +- org.junit.platform:junit-platform-commons:jar:1.11.4:test (version managed from 1.11.4)
+[INFO] |  |  |  |  \- (org.apiguardian:apiguardian-api:jar:1.1.2:test - omitted for duplicate)
+[INFO] |  |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
+[INFO] |  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.11.4:test (version managed from 5.11.4)
+[INFO] |  |  |  +- (org.junit.jupiter:junit-jupiter-api:jar:5.11.4:test - version managed from 5.11.4; omitted for duplicate)
+[INFO] |  |  |  \- (org.apiguardian:apiguardian-api:jar:1.1.2:test - omitted for duplicate)
+[INFO] |  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.11.4:test (version managed from 5.11.4)
+[INFO] |  |     +- org.junit.platform:junit-platform-engine:jar:1.11.4:test (version managed from 1.11.4)
+[INFO] |  |     |  +- (org.opentest4j:opentest4j:jar:1.3.0:test - omitted for duplicate)
+[INFO] |  |     |  +- (org.junit.platform:junit-platform-commons:jar:1.11.4:test - version managed from 1.11.4; omitted for duplicate)
+[INFO] |  |     |  \- (org.apiguardian:apiguardian-api:jar:1.1.2:test - omitted for duplicate)
+[INFO] |  |     +- (org.junit.jupiter:junit-jupiter-api:jar:5.11.4:test - version managed from 5.11.4; omitted for duplicate)
+[INFO] |  |     \- (org.apiguardian:apiguardian-api:jar:1.1.2:test - omitted for duplicate)
+[INFO] |  +- org.mockito:mockito-core:jar:5.14.2:test (version managed from 5.14.2)
+[INFO] |  |  +- (net.bytebuddy:byte-buddy:jar:1.15.11:test - version managed from 1.15.4; omitted for duplicate)
+[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.15.11:test (version managed from 1.15.4)
+[INFO] |  |  \- org.objenesis:objenesis:jar:3.3:test
+[INFO] |  +- org.mockito:mockito-junit-jupiter:jar:5.14.2:test (version managed from 5.14.2)
+[INFO] |  |  +- (org.mockito:mockito-core:jar:5.14.2:test - version managed from 5.14.2; omitted for duplicate)
+[INFO] |  |  \- (org.junit.jupiter:junit-jupiter-api:jar:5.11.4:test - version managed from 5.11.2; omitted for duplicate)
+[INFO] |  +- org.skyscreamer:jsonassert:jar:1.5.3:test (version managed from 1.5.3)
+[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
+[INFO] |  +- org.springframework:spring-core:jar:6.2.5:compile (version managed from 6.2.5; scope not updated to compile)
+[INFO] |  |  \- org.springframework:spring-jcl:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |  +- org.springframework:spring-test:jar:6.2.5:test (version managed from 6.2.5)
+[INFO] |  |  \- (org.springframework:spring-core:jar:6.2.5:test - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  \- org.xmlunit:xmlunit-core:jar:2.10.0:test (version managed from 2.10.0)
+[INFO] |     \- (jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.2:test - version managed from 2.3.3; omitted for duplicate)
+[INFO] +- org.springframework.boot:spring-boot-starter-validation:jar:3.4.4:compile
+[INFO] |  +- (org.springframework.boot:spring-boot-starter:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.39:compile (version managed from 10.1.39)
+[INFO] |  \- org.hibernate.validator:hibernate-validator:jar:8.0.2.Final:compile (version managed from 8.0.2.Final)
+[INFO] |     +- jakarta.validation:jakarta.validation-api:jar:3.0.2:compile (version managed from 3.0.2)
+[INFO] |     +- org.jboss.logging:jboss-logging:jar:3.6.1.Final:compile (version managed from 3.4.3.Final)
+[INFO] |     \- com.fasterxml:classmate:jar:1.7.0:compile (version managed from 1.5.1)
+[INFO] +- org.springframework.boot:spring-boot-starter-security:jar:3.4.4:compile
+[INFO] |  +- (org.springframework.boot:spring-boot-starter:jar:3.4.4:compile - version managed from 3.4.4; omitted for duplicate)
+[INFO] |  +- org.springframework:spring-aop:jar:6.2.5:compile (version managed from 6.2.5)
+[INFO] |  |  +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  |  \- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.5; omitted for duplicate)
+[INFO] |  +- org.springframework.security:spring-security-config:jar:6.4.4:compile (version managed from 6.4.4)
+[INFO] |  |  +- org.springframework.security:spring-security-core:jar:6.4.4:compile (version managed from 6.4.4)
+[INFO] |  |  |  +- org.springframework.security:spring-security-crypto:jar:6.4.4:compile (version managed from 6.4.4)
+[INFO] |  |  |  +- (org.springframework:spring-aop:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  |  +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  |  +- (org.springframework:spring-context:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  |  +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  |  +- (org.springframework:spring-expression:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  |  \- (io.micrometer:micrometer-observation:jar:1.14.5:compile - version managed from 1.14.5; omitted for duplicate)
+[INFO] |  |  +- (org.springframework:spring-aop:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  +- (org.springframework:spring-context:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  |  \- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |  \- org.springframework.security:spring-security-web:jar:6.4.4:compile (version managed from 6.4.4)
+[INFO] |     +- (org.springframework.security:spring-security-core:jar:6.4.4:compile - version managed from 6.4.4; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-core:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-aop:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-beans:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-context:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |     +- (org.springframework:spring-expression:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] |     \- (org.springframework:spring-web:jar:6.2.5:compile - version managed from 6.2.4; omitted for duplicate)
+[INFO] +- io.jsonwebtoken:jjwt-api:jar:0.11.5:compile
+[INFO] +- io.jsonwebtoken:jjwt-impl:jar:0.11.5:runtime
+[INFO] |  \- (io.jsonwebtoken:jjwt-api:jar:0.11.5:runtime - omitted for duplicate)
+[INFO] \- io.jsonwebtoken:jjwt-jackson:jar:0.11.5:runtime
+[INFO]    +- (io.jsonwebtoken:jjwt-api:jar:0.11.5:runtime - omitted for duplicate)
+[INFO]    \- (com.fasterxml.jackson.core:jackson-databind:jar:2.18.3:runtime - version managed from 2.12.6.1; omitted for duplicate)
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD SUCCESS
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time:  8.939 s
+[INFO] Finished at: 2025-05-10T00:10:04+08:00
+[INFO] ------------------------------------------------------------------------
diff --git a/backend/demo/pom.xml b/backend/demo/pom.xml
index fb51278..bac660b 100644
--- a/backend/demo/pom.xml
+++ b/backend/demo/pom.xml
@@ -1,74 +1,112 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>org.springframework.boot</groupId>
-		<artifactId>spring-boot-starter-parent</artifactId>
-		<version>3.4.4</version>
-		<relativePath/> 
-	</parent>
-	<groupId>com.example</groupId>
-	<artifactId>demo</artifactId>
-	<version>0.0.1-SNAPSHOT</version>
-	<name>demo</name>
-	<description>Demo project for Spring Boot</description>
-	<url/>
-	<licenses>
-		<license/>
-	</licenses>
-	<developers>
-		<developer/>
-	</developers>
-	<scm>
-		<connection/>
-		<developerConnection/>
-		<tag/>
-		<url/>
-	</scm>
-	<properties>
-		<java.version>17</java.version>
-	</properties>
-	<dependencies>
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-data-jpa</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-web</artifactId>
-		</dependency>
 
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-docker-compose</artifactId>
-			<scope>runtime</scope>
-			<optional>true</optional>
-		</dependency>
-		<dependency>
-			<groupId>com.mysql</groupId>
-			<artifactId>mysql-connector-j</artifactId>
-			<scope>runtime</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-test</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-           <groupId>com.h2database</groupId>
-           <artifactId>h2</artifactId>
-           <scope>runtime</scope>
-        </dependency>
-	</dependencies>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.springframework.boot</groupId>
-				<artifactId>spring-boot-maven-plugin</artifactId>
-			</plugin>
-		</plugins>
-	</build>
+<modelVersion>4.0.0</modelVersion>
+
+<parent>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-parent</artifactId>
+    <version>3.4.4</version>
+    <relativePath/>
+</parent>
+
+<groupId>com.example</groupId>
+<artifactId>demo</artifactId>
+<version>0.0.1-SNAPSHOT</version>
+<name>demo</name>
+<description>Demo project for Spring Boot</description>
+
+<properties>
+    <java.version>17</java.version>
+</properties>
+
+<dependencies>
+    <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-web</artifactId>
+    </dependency>
+    
+
+    <!-- 数据库驱动:MySQL、H2 -->
+    <dependency>
+        <groupId>com.mysql</groupId>
+        <artifactId>mysql-connector-j</artifactId>
+        <scope>runtime</scope>
+    </dependency>
+   
+
+    <!-- MyBatis-Plus -->
+    <dependency>
+        <groupId>com.baomidou</groupId>
+        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
+        <version>3.5.5</version>
+    </dependency>
+<!-- <dependency>
+  DO NOT DO THIS
+        <groupId>com.baomidou</groupId>
+        <artifactId>mybatis-plus-boot-starter</artifactId>
+        <version>3.5.5</version>
+    </dependency>
+-->
+    <!-- Spring Boot 配置处理器(可选) -->
+    <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-configuration-processor</artifactId>
+        <optional>true</optional>
+    </dependency>
+
+    <!-- Docker Compose 支持 -->
+    <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-docker-compose</artifactId>
+        <scope>runtime</scope>
+        <optional>true</optional>
+    </dependency>
+
+    <!-- 单元测试 -->
+    <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-test</artifactId>
+        <scope>test</scope>
+    </dependency>
+     <dependency>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-validation</artifactId>
+</dependency>
+ <dependency>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-security</artifactId>
+</dependency>
+ <dependency>
+  <groupId>io.jsonwebtoken</groupId>
+  <artifactId>jjwt-api</artifactId>
+  <version>0.11.5</version>
+</dependency>
+<dependency>
+  <groupId>io.jsonwebtoken</groupId>
+  <artifactId>jjwt-impl</artifactId>
+  <version>0.11.5</version>
+  <scope>runtime</scope>
+</dependency>
+<dependency>
+  <groupId>io.jsonwebtoken</groupId>
+  <artifactId>jjwt-jackson</artifactId>
+  <version>0.11.5</version>
+  <scope>runtime</scope>
+</dependency>
+
+</dependencies>
+
+<build>
+    <plugins>
+        <plugin>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-maven-plugin</artifactId>
+        </plugin>
+    </plugins>
+</build>
 
 </project>
diff --git a/backend/demo/src/main/java/com/example/demo/DemoApplication.java b/backend/demo/src/main/java/com/example/demo/DemoApplication.java
index 1f94219..8575ec8 100644
--- a/backend/demo/src/main/java/com/example/demo/DemoApplication.java
+++ b/backend/demo/src/main/java/com/example/demo/DemoApplication.java
@@ -1,8 +1,10 @@
 package com.example.demo;
 
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 @SpringBootApplication
+@MapperScan("com.example.demo.mapper")
 public class DemoApplication {
 
 	public static void main(String[] args) {
diff --git a/backend/demo/src/main/java/com/example/demo/config/JWTProperties.java b/backend/demo/src/main/java/com/example/demo/config/JWTProperties.java
new file mode 100644
index 0000000..e96ed56
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/config/JWTProperties.java
@@ -0,0 +1,91 @@
+package com.example.demo.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * JWT 配置属性,从 application.properties 中 jwt 开头的配置加载
+ */
+@Component
+@ConfigurationProperties(prefix = "jwt")
+public class JWTProperties {
+    /**
+     * 用于签名的密钥
+     */
+    private String secret;
+
+    /**
+     * Token 过期时长,单位毫秒
+     */
+    private long expirationMs;
+
+    /**
+     * HTTP Header 中放置 JWT 的字段名
+     */
+    private String header = "Authorization";
+
+    /**
+     * Header 中 Token 的前缀
+     */
+    private String tokenPrefix = "Bearer ";
+
+    /**
+     * 签发者信息(可选)
+     */
+    private String issuer;
+
+    /**
+     * 接收者信息(可选)
+     */
+    private String audience;
+
+    // --- getters & setters ---
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public long getExpirationMs() {
+        return expirationMs;
+    }
+
+    public void setExpirationMs(long expirationMs) {
+        this.expirationMs = expirationMs;
+    }
+
+    public String getHeader() {
+        return header;
+    }
+
+    public void setHeader(String header) {
+        this.header = header;
+    }
+
+    public String getTokenPrefix() {
+        return tokenPrefix;
+    }
+
+    public void setTokenPrefix(String tokenPrefix) {
+        this.tokenPrefix = tokenPrefix;
+    }
+
+    public String getIssuer() {
+        return issuer;
+    }
+
+    public void setIssuer(String issuer) {
+        this.issuer = issuer;
+    }
+
+    public String getAudience() {
+        return audience;
+    }
+
+    public void setAudience(String audience) {
+        this.audience = audience;
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/config/SecurityConfig.java b/backend/demo/src/main/java/com/example/demo/config/SecurityConfig.java
new file mode 100644
index 0000000..bfd7b1b
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/config/SecurityConfig.java
@@ -0,0 +1,51 @@
+package com.example.demo.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+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 com.example.demo.security.JwtAuthenticationFilter;
+import com.example.demo.security.JwtTokenUtil;
+
+@Configuration
+public class SecurityConfig {
+
+    /**
+     * 密码加密器,用于注册用户时对密码加密、登录时校验
+     */
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    /**
+     * 将 Spring Security 的 AuthenticationManager 暴露为 Bean,
+     * 方便在 AuthController 或其它地方手动调用。
+     */
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
+        return config.getAuthenticationManager();
+    }
+
+    /**
+     * 核心安全策略:禁用 CSRF、无状态 Session、开放登录接口、其余接口需认证。
+     */
+    @Bean
+public SecurityFilterChain filterChain(HttpSecurity http,
+                                       JwtTokenUtil tokenUtil,
+                                       JWTProperties props) throws Exception {
+    JwtAuthenticationFilter jwtFilter = new JwtAuthenticationFilter(tokenUtil, props);
+    http
+      // 省略其他配置…
+      .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
+    return http.build();
+}
+}
+
diff --git a/backend/demo/src/main/java/com/example/demo/controller/AuthController.java b/backend/demo/src/main/java/com/example/demo/controller/AuthController.java
new file mode 100644
index 0000000..08411d7
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/controller/AuthController.java
@@ -0,0 +1,74 @@
+package com.example.demo.controller;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.example.demo.dto.LoginRequestDTO;
+import com.example.demo.dto.LoginResponseDTO;
+import com.example.demo.entity.User;
+import com.example.demo.exception.AuthException;
+import com.example.demo.security.JwtTokenUtil;
+import com.example.demo.service.UserService;
+
+import jakarta.validation.Valid;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+    private final UserService userService;
+    private final PasswordEncoder passwordEncoder;
+    private final JwtTokenUtil jwtTokenUtil;
+
+    @Autowired
+    public AuthController(UserService userService,
+                          PasswordEncoder passwordEncoder,
+                          JwtTokenUtil jwtTokenUtil) {
+        this.userService = userService;
+        this.passwordEncoder = passwordEncoder;
+        this.jwtTokenUtil = jwtTokenUtil;
+    }
+
+    @PostMapping("/login")
+    public ResponseEntity<?> login(
+            @Valid @RequestBody LoginRequestDTO loginRequest,
+            BindingResult bindingResult) {
+
+        if (bindingResult.hasErrors()) {
+            String errMsg = bindingResult.getFieldErrors().stream()
+                .map(fe -> fe.getField() + ": " + fe.getDefaultMessage())
+                .reduce((a, b) -> a + "; " + b)
+                .orElse("Invalid parameters");
+            return ResponseEntity.badRequest().body(Map.of("error", errMsg));
+        }
+
+        User user = userService.lambdaQuery()
+                .eq(User::getUsername, loginRequest.getUsername())
+                .one();
+
+        if (user == null || !passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
+            throw new AuthException("用户名或密码错误");
+        }
+
+        String token = jwtTokenUtil.generateToken(user.getId(), user.getUsername(), user.getRole());
+
+        LoginResponseDTO response = new LoginResponseDTO();
+        response.setToken(token);
+        response.setExpiresAt(Instant.now().plusMillis(jwtTokenUtil.getExpiration()));
+        response.setUserId(user.getId());
+        response.setUsername(user.getUsername());
+        response.setRoles(List.of(user.getRole()));
+
+        return ResponseEntity.ok(response);
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/dto/LoginRequestDTO.java b/backend/demo/src/main/java/com/example/demo/dto/LoginRequestDTO.java
new file mode 100644
index 0000000..8c85fec
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/dto/LoginRequestDTO.java
@@ -0,0 +1,32 @@
+package com.example.demo.dto;
+
+import java.io.Serializable;
+
+import jakarta.validation.constraints.NotBlank;
+
+
+public class LoginRequestDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @NotBlank(message = "用户名不能为空")
+    private String username;
+
+    @NotBlank(message = "密码不能为空")
+    private String password;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}
\ No newline at end of file
diff --git a/backend/demo/src/main/java/com/example/demo/dto/LoginResponseDTO.java b/backend/demo/src/main/java/com/example/demo/dto/LoginResponseDTO.java
new file mode 100644
index 0000000..2dd6241
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/dto/LoginResponseDTO.java
@@ -0,0 +1,64 @@
+package com.example.demo.dto;
+
+import java.io.Serializable;
+import java.time.Instant;
+import java.util.List;
+
+public class LoginResponseDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 登录成功后返回的 JWT 或会话标识 */
+    private String token;
+
+    /** Token 过期时间戳 */
+    private Instant expiresAt;
+
+    /** 用户 ID,可选 */
+    private Long userId;
+
+    /** 用户名,可选 */
+    private String username;
+
+    /** 用户角色列表,可选 */
+    private List<String> roles;
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public Instant getExpiresAt() {
+        return expiresAt;
+    }
+
+    public void setExpiresAt(Instant expiresAt) {
+        this.expiresAt = expiresAt;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public List<String> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(List<String> roles) {
+        this.roles = roles;
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/entity/User.java b/backend/demo/src/main/java/com/example/demo/entity/User.java
new file mode 100644
index 0000000..bcbe6de
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/entity/User.java
@@ -0,0 +1,105 @@
+package com.example.demo.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+
+@TableName("user")
+public class User implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String username;
+
+    private String password;
+
+    private String email;
+
+    private Integer status; 
+
+    private Integer score; 
+
+    private String role; 
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public Integer getScore() {
+        return score;
+    }
+
+    public void setScore(Integer score) {
+        this.score = score;
+    }
+
+    public String getRole() {
+        return role;
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/exception/AuthException.java b/backend/demo/src/main/java/com/example/demo/exception/AuthException.java
new file mode 100644
index 0000000..526f1da
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/exception/AuthException.java
@@ -0,0 +1,14 @@
+package com.example.demo.exception;
+
+/**
+ * 自定义认证/授权异常
+ */
+public class AuthException extends RuntimeException {
+    public AuthException(String message) {
+        super(message);
+    }
+
+    public AuthException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java b/backend/demo/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..bc560e6
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/exception/GlobalExceptionHandler.java
@@ -0,0 +1,39 @@
+package com.example.demo.exception;
+
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+    /** 处理自定义认证异常 */
+    @ExceptionHandler(AuthException.class)
+    public ResponseEntity<Map<String, String>> handleAuthException(AuthException ex) {
+        Map<String, String> body = Map.of("error", ex.getMessage());
+        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(body);
+    }
+
+    /** 处理请求参数校验失败 */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
+        Map<String, String> errors = new HashMap<>();
+        for (FieldError fe : ex.getBindingResult().getFieldErrors()) {
+            errors.put(fe.getField(), fe.getDefaultMessage());
+        }
+        return ResponseEntity.badRequest().body(errors);
+    }
+
+    /** 处理其它未捕获的异常 */
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<Map<String, String>> handleAllExceptions(Exception ex) {
+        Map<String, String> body = Map.of("error", "Internal server error");
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/mapper/UserMapper.java b/backend/demo/src/main/java/com/example/demo/mapper/UserMapper.java
new file mode 100644
index 0000000..94ba7a8
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/mapper/UserMapper.java
@@ -0,0 +1,17 @@
+package com.example.demo.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.demo.entity.User;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * UserMapper 接口
+ * 
+ * 继承 MyBatis-Plus 提供的 BaseMapper,实现基本的 CRUD 操作
+ */
+@Mapper
+public interface UserMapper extends BaseMapper<User> {
+    
+    // List<User> selectByStatus(@Param("status") Integer status);
+}
+
diff --git a/backend/demo/src/main/java/com/example/demo/security/JwtAuthenticationFilter.java b/backend/demo/src/main/java/com/example/demo/security/JwtAuthenticationFilter.java
new file mode 100644
index 0000000..108e966
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/security/JwtAuthenticationFilter.java
@@ -0,0 +1,64 @@
+package com.example.demo.security;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import com.example.demo.config.JWTProperties;
+import com.example.demo.exception.AuthException;
+
+import io.jsonwebtoken.Claims;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+@Component 
+public class JwtAuthenticationFilter extends OncePerRequestFilter {
+
+    private final JwtTokenUtil tokenUtil;
+    private final JWTProperties props;
+
+    public JwtAuthenticationFilter(JwtTokenUtil tokenUtil, JWTProperties props) {
+        this.tokenUtil = tokenUtil;
+        this.props = props;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request,
+                                    HttpServletResponse response,
+                                    FilterChain chain)
+            throws ServletException, IOException {
+
+        String headerValue = request.getHeader(props.getHeader());
+        if (!StringUtils.hasText(headerValue) || !headerValue.startsWith(props.getTokenPrefix())) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        String token = headerValue.substring(props.getTokenPrefix().length());
+        if (!tokenUtil.validateToken(token)) {
+            throw new AuthException("Invalid or expired JWT token");
+        }
+
+        Claims claims = tokenUtil.parseClaims(token);
+        String username = claims.getSubject();
+        Long userId = tokenUtil.getUserId(token);
+        String role = tokenUtil.getRole(token);
+
+        UsernamePasswordAuthenticationToken auth =
+            new UsernamePasswordAuthenticationToken(
+                userId, 
+                null, 
+                List.of(new SimpleGrantedAuthority(role))
+            );
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        chain.doFilter(request, response);
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/security/JwtTokenUtil.java b/backend/demo/src/main/java/com/example/demo/security/JwtTokenUtil.java
new file mode 100644
index 0000000..3f44d8a
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/security/JwtTokenUtil.java
@@ -0,0 +1,81 @@
+package com.example.demo.security;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+import com.example.demo.config.JWTProperties;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.Keys;
+@Component
+public class JwtTokenUtil {
+
+    private final JWTProperties props;
+    private final byte[] secretBytes;
+
+    public JwtTokenUtil(JWTProperties props) {
+        this.props = props;
+        this.secretBytes = props.getSecret().getBytes(StandardCharsets.UTF_8);
+    }
+
+    /** 生成 JWT */
+    public String generateToken(Long userId, String username, String role) {
+        Date now = new Date();
+        Date expiry = new Date(now.getTime() + props.getExpirationMs());
+
+        return Jwts.builder()
+                .setSubject(username)
+                .setIssuer(props.getIssuer())
+                .setAudience(props.getAudience())
+                .setIssuedAt(now)
+                .setExpiration(expiry)
+                .addClaims(Map.of("userId", userId, "role", role))
+                .signWith(Keys.hmacShaKeyFor(secretBytes), SignatureAlgorithm.HS256)
+                .compact();
+    }
+
+    /** 验证并解析 Token,抛出异常则验证失败 */
+    public Claims parseClaims(String token) {
+        return Jwts.parserBuilder()
+                .setSigningKey(secretBytes)
+                .build()
+                .parseClaimsJws(token)
+                .getBody();
+    }
+
+    /** 校验 Token 是否有效 */
+    public boolean validateToken(String token) {
+        try {
+            parseClaims(token);
+            return true;
+        } catch (JwtException e) {
+            return false;
+        }
+    }
+
+    /** 从 Token 获取用户名(Subject) */
+    public String getUsername(String token) {
+        return parseClaims(token).getSubject();
+    }
+
+    /** 从 Token 获取用户 ID */
+    public Long getUserId(String token) {
+        Object id = parseClaims(token).get("userId");
+        return id == null ? null : Long.valueOf(id.toString());
+    }
+
+    /** 从 Token 获取角色 */
+    public String getRole(String token) {
+        return parseClaims(token).get("role", String.class);
+    }
+
+    public long getExpiration() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+}
diff --git a/backend/demo/src/main/java/com/example/demo/service/UserService.java b/backend/demo/src/main/java/com/example/demo/service/UserService.java
new file mode 100644
index 0000000..60e8aef
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/service/UserService.java
@@ -0,0 +1,13 @@
+package com.example.demo.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.example.demo.entity.User;
+
+/**
+ * User 业务层接口
+ */
+public interface UserService extends IService<User> {
+    // 如果需要自定义方法,可以在这里再添加,例如:
+    // User findByUsername(String username);
+}
diff --git a/backend/demo/src/main/java/com/example/demo/service/impl/UserServiceImpl.java b/backend/demo/src/main/java/com/example/demo/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..5bd1693
--- /dev/null
+++ b/backend/demo/src/main/java/com/example/demo/service/impl/UserServiceImpl.java
@@ -0,0 +1,23 @@
+package com.example.demo.service.impl;
+
+// UserServiceImpl.java
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.entity.User;
+import com.example.demo.mapper.UserMapper;
+import com.example.demo.service.UserService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * User 业务层默认实现
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
+    // 如果你在接口中声明了自定义方法,这里可以重写并实现:
+    // @Override
+    // public User findByUsername(String username) {
+    //     return lambdaQuery().eq(User::getUsername, username).one();
+    // }
+}
diff --git a/backend/demo/src/main/resources/application.properties b/backend/demo/src/main/resources/application.properties
index 90968f5..4472028 100644
--- a/backend/demo/src/main/resources/application.properties
+++ b/backend/demo/src/main/resources/application.properties
@@ -1,10 +1,12 @@
-# H2 Configuration (Ensure these are uncommented)
-spring.datasource.url=jdbc:h2:mem:testdb
-spring.datasource.driver-class-name=org.h2.Driver
-spring.datasource.username=sa
-spring.datasource.password=
-spring.h2.console.enabled=true
+# ========== 数据源 ==========
+spring.datasource.url=jdbc:mysql://mysql:3306/mydatabase?serverTimezone=Asia/Shanghai
+spring.datasource.username=myuser
+spring.datasource.password=secret
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 
-# Required for JPA/Hibernate
-spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
-spring.jpa.hibernate.ddl-auto=update
\ No newline at end of file
+# ========== JWT 配置 ==========
+jwt.secret=YourJWTSecretKeyHere1234567890
+jwt.expirationMs=3600000
+
+# ========== 日志输出(可选) ==========
+logging.level.org.springframework.security=DEBUG