7.5 KiB
PEVC 式本地密码镜像 Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 让智云教师/学生在本系统完成 SSO 或 CAS 后,以其智云账号和密码直接登录本系统;本地只保存 BCrypt 密码哈希。
Architecture: 保留现有主平台 Token/CAS 身份校验。验证成功后,独立的只读凭据查询从 core_user.PASSWORD 获取当前密码(不进入 Token、日志或 API),投影服务立即 BCrypt 编码并更新 sys_user.password_hash。本地 /api/v1/auth/login 仅校验本地哈希并签发本系统 JWT。
Tech Stack: Java 17, Spring Boot 4.1, Spring Security BCryptPasswordEncoder, MyBatis-Plus, Flyway, MySQL.
Global Constraints
- 不修改
E:\javawork\tianze-pro;主平台数据源保持只读 SELECT。 - 密码明文只在读取、BCrypt 编码和校验期间短暂存在,禁止日志、响应、Token、快照表或迁移脚本保存。
- 仅支持从智云识别出的
TEACHER、STUDENT;无用户/角色 CRUD API。 - 参照 PEVC 的
UserDataMigration与AccountService:外部密码 BCrypt 后本地保存,本地登录只校验本地密码哈希。
Task 1: 主平台只读凭据查询与密码投影
Files:
- Create:
src/main/java/com/yau/digitalrmb/platformintegration/application/PlatformCredentialRepository.java - Create:
src/main/java/com/yau/digitalrmb/platformintegration/domain/PlatformCredential.java - Modify:
src/main/java/com/yau/digitalrmb/platformintegration/infrastructure/JdbcPlatformIdentityRepository.java - Modify:
src/main/java/com/yau/digitalrmb/identity/application/PlatformIdentityProjectionService.java - Test:
src/test/java/com/yau/digitalrmb/platformintegration/infrastructure/JdbcPlatformIdentityRepositoryTest.java - Test:
src/test/java/com/yau/digitalrmb/identity/PlatformIdentityProjectionServiceTest.java
Interfaces:
-
Produces
Optional<PlatformCredential> findCredential(long platformUserId). -
PlatformCredentialcontainsPlatformActor actorandString rawPassword; it has notoStringlogging implementation. -
void project(PlatformCredential credential)storespasswordEncoder.encode(credential.rawPassword())insys_user.password_hash. -
Write failing tests proving the credentials query only returns enabled teacher/student records and that projection stores a BCrypt value matching the source password.
-
Run the targeted tests; expect compilation failure for missing credential types.
-
Implement the secondary SELECT for
core_user.PASSWORD, the BCryptPasswordEncoderbean, and projection overload. The existing actor-only projection remains for metadata sync and must not change password hashes. -
Run
mvn '-Dtest=JdbcPlatformIdentityRepositoryTest,PlatformIdentityProjectionServiceTest' test -DforkCount=0 -B; expect success. -
Commit with
feat: mirror platform credentials securely.
Task 2: 生产本地用户名密码登录
Files:
- Create:
src/main/java/com/yau/digitalrmb/security/application/LocalAccountAuthenticationService.java - Modify:
src/main/java/com/yau/digitalrmb/security/interfaces/AuthController.java - Delete:
src/main/java/com/yau/digitalrmb/security/interfaces/BootstrapLoginController.java - Delete:
src/main/java/com/yau/digitalrmb/security/application/BootstrapAdminAuthenticator.java - Modify:
src/main/java/com/yau/digitalrmb/security/config/SecurityConfig.java - Test:
src/test/java/com/yau/digitalrmb/security/AuthControllerTest.java
Interfaces:
-
JwtTokenService.Token login(String username, String rawPassword)resolves enabledsys_user, checks BCrypt, readsplatform_user_snapshot, and issues a role-bearing JWT. -
POST /api/v1/auth/loginaccepts existingLoginRequestand returnsLoginResponse; it is anonymously reachable in every profile. -
Replace the bootstrap-login regression test with a failing test that projects
tzs001using source password123qwe, posts it to/api/v1/auth/login, and expects an access token. -
Run
mvn -Dtest=AuthControllerTest test -DforkCount=0 -B; expect failure because the production login service does not exist. -
Implement local lookup, BCrypt verification,
TEACHER/STUDENTrole extraction, and the controller endpoint. ReturnUNAUTHORIZEDfor unknown, disabled, wrong-password, or non-projected users. Remove the bootstrap-only controller so no duplicate route exists. -
Run
mvn '-Dtest=AuthControllerTest,CurrentUserAndLogoutTest' test -DforkCount=0 -B; expect success. -
Commit with
feat: add local password login.
Task 3: SSO/CAS 密码初始化与 tzs001 启动初始化
Files:
- Modify:
src/main/java/com/yau/digitalrmb/platformintegration/interfaces/PlatformSsoController.java - Modify:
src/main/java/com/yau/digitalrmb/platformintegration/interfaces/CasAuthenticationController.java - Create:
src/main/java/com/yau/digitalrmb/identity/application/PlatformCredentialInitializer.java - Modify:
src/main/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationProperties.java - Modify:
src/main/resources/application-local.yml - Test:
src/test/java/com/yau/digitalrmb/platformintegration/interfaces/PlatformSsoControllerTest.java - Test:
src/test/java/com/yau/digitalrmb/identity/PlatformCredentialInitializerTest.java
Interfaces:
-
Both successful SSO and CAS flows call
credentialRepository.findCredential(actor.platformUserId())followed byprojectionService.project(credential)before issuing an exchange code. -
platform-integration.local-login.initial-accountsdefaults to an empty list; local profile containstzs001so startup initializes it from the platform read-only database. -
Write failing tests proving SSO invokes credential projection and the initializer only initializes configured accounts.
-
Run target tests; expect missing initializer behavior.
-
Implement no-logging credential projection in both flows and the explicit configurable initializer. It must skip absent/disabled/non-teacher/non-student accounts without creating local users.
-
Run
mvn '-Dtest=PlatformSsoControllerTest,PlatformCredentialInitializerTest,AuthControllerTest' test -DforkCount=0 -B; expect success. -
Commit with
feat: initialize local passwords from platform login.
Task 4: Verification and operations documentation
Files:
-
Modify:
README.md -
Modify:
docs/superpowers/specs/2026-08-03-platform-sso-readonly-design.md -
Test:
src/test/java/com/yau/digitalrmb/security/EndToEndAuthenticationFlowTest.java -
Write an end-to-end failing test: source credential → SSO projection → local
/login→/me; assert no raw password occurs in snapshots or JWT claims. -
Implement only documentation and any wiring exposed by that test.
-
Document that local profile initializes
tzs001from the platform DB; never document or source-control a password. -
Run
mvn test -DforkCount=0 -Bandmvn package -DskipTests -B; expect zero test failures and a generated executable JAR. -
Commit with
docs: document local password mirror login.
Plan Self-Review
- PEVC alignment: Task 1 matches external credential migration with BCrypt; Task 2 matches PEVC local
AccountService.login; Task 3 ensures SSO/CAS create or refresh local credentials. - Password handling: every task forbids raw password persistence outside the source read and BCrypt transformation.
- Scope: no change is made to the upstream platform or to public user/role CRUD.