Skip to content

Migrate ACL from Sa-Token to Spring Security with JWT - #3

Open
willzou2012 wants to merge 1 commit into
DCSCDF:main_1from
willzou2012:migrate/satoken-to-spring-security
Open

willzou2012 wants to merge 1 commit into
DCSCDF:main_1from
willzou2012:migrate/satoken-to-spring-security

Conversation

@willzou2012

Copy link
Copy Markdown

Summary

Migrates the ACL from Sa-Token to Spring Security with stateless JWT, and removes Sa-Token completely (dependency, annotations, session store, result/KV types, and a stray vendored Sa-Token source file tracked at the repo root). A repo-wide sweep for Sa-Token references now returns 0 matches.

Login & sessions

  • Login keeps its existing flow (captcha, one-time temp token, RSA-encrypted password, BCrypt check, disabled-account rejection) and now issues an HS256 JWT via JwtService (JJWT): 30 days with "remember me", otherwise a 2-hour hard expiry (the former sliding active-timeout cannot slide with JWT).
  • Requests authenticate through JwtAuthenticationFilter. Authorization: Bearer <token> is canonical; the legacy token: header is still accepted and login still returns {token}, so the existing frontend needs no changes.
  • Session semantics are preserved with a jti registry (ActiveTokenRegistry): logout revokes the current token; password change, account disable, and account delete revoke all of the user's tokens; a new login revokes previously issued tokens (single-session, matching the former is-concurrent=false).

Authorization

  • All 72 @SaCheckPermission/@SaCheckRole checks were converted to @PreAuthorize("hasAuthority('...')") / hasRole('...') with identical permission codes (guarded by PreAuthorizeMappingTest, which asserts representative codes and the total count).
  • Authorities are resolved per request by BlogUserDetailsService from the unchanged RBAC tables: ROLE_<roleCode> plus permission codes with the existing parent-expansion rule (a parent permission implies all children; super-admin gets every registered permission). Role/permission edits and account disabling therefore take effect immediately.
  • URL rules in SecurityConfig: /api/public/**, /api/images/**, /api/captcha/**, and auth entry points (login/register/password-reset/OAuth/public-key) are anonymous; everything else requires authentication. 401/403 responses keep the project's unified Response JSON shape (GlobalExceptionHandler + security entry points).

SaResult / SaTokenDao swap

  • SaResult -> ServiceResult (common/ServiceResult) with an identical data/error/ok/setCode/getCode/getData/getMsg contract, so service signatures and controller handling did not churn.
  • SaTokenDao (used as a generic TTL scratch store) -> TtlStore for temp-login tokens, OAuth codes, and pending register/password-reset/email-change records; SaFoxUtil -> TokenGenerator.

Config

  • sa-token.* properties replaced by app.jwt.* (JWT_SECRET env, issuer, expirations). Production must set a strong JWT_SECRET (>= 32 chars); the committed default is dev-only.

Incidentals

  • Renamed permissionService.java/permissionServiceImpl.java to PermissionService.java/PermissionServiceImpl.java (public type names) so the project compiles on case-sensitive filesystems.
  • Docs updated (README auth section, Document/Permission_Hierarchy.md, API docs).

Review guide

  • Start with config/system/SecurityConfig.java, security/ (filter, JWT, registry, user-details), and service/user/auth/AuthServiceImpl.java (login/logout/password session behavior). The bulk of the remaining diff is mechanical: SaResult -> ServiceResult renames and @SaCheck* -> @PreAuthorize conversions.
  • New files: common/ServiceResult.java, common/TtlStore.java, security/*.java, utils/security/TokenGenerator.java. Deleted: config/system/SaTokenConfig.java, cn/dev33/satoken/exception/NotLoginException.java.

Test Plan

  • mvn test: 56 tests run, 0 failures (JDK 23, -Dmaven.compiler.proc=full; on JDK 17 the flag is unnecessary).
  • Suites: JWT issue/parse/tamper/revoke and remember-me expiry; HTTP filter chain (anonymous 401, Bearer + legacy header, permission/role 403/200, revoked/disabled/malformed token, public URL with garbage token); authority loading (ROLE_ prefix, disabled/deleted users); login-session flow with real RSA/BCrypt/JWT (single-session revoke, logout, password-change revoke); forced logout on user disable/delete; scratch-store one-time/attempt/rate-limit semantics; 401/403 exception mapping; @PreAuthorize mapping/count guard; CORS headers; plus the pre-existing MyblogDevApplicationTests.contextLoads.
  • Pre-existing environment notes (unrelated to this change): org.wltea:ik-analyzer:2012_u6 is not published to Maven Central, so a fully clean machine cannot resolve the stock pom (verified locally with a stub installed only in the local Maven repo); the H2 test schema logs table-init warnings during contextLoads, as before.

Rollback

Revert this single commit; the RBAC schema and API contracts are unchanged, and tokens issued before/after are not cross-compatible (users simply log in again).

Summary:
- Login/sessions: replace Sa-Token opaque tokens and session store with
  stateless JWT (HS256, JJWT) issued at login; Bearer is canonical and the
  legacy token header is still accepted so the frontend is unchanged.
  Logout, password change, user disable/delete revoke tokens via a jti
  registry; new login revokes previous tokens (single-session).
- Authorization: convert all 72 SaCheck checks to @PreAuthorize with
  identical permission codes; load ROLE_* + parent-expanded permissions
  per request from the unchanged RBAC tables.
- Replace SaResult with ServiceResult and SaTokenDao with TtlStore
  (identical contracts); remove the Sa-Token dependency and the stray
  vendored Sa-Token file at the repo root (zero references remain).
- Rename permissionService files to match their public type names so the
  build works on case-sensitive filesystems; update docs and config
  (sa-token.* -> app.jwt.*, JWT_SECRET from env).

Test Plan:
- mvn test: 56 tests run, 0 failures. New suites cover JWT issue/parse/
  revoke, HTTP filter chain (401/403, Bearer + legacy header, revoked/
  disabled/malformed tokens), authority loading, login-session flow with
  real RSA/BCrypt/JWT, forced logout on disable/delete, scratch-store
  semantics, exception mapping, @PreAuthorize mapping guard, CORS, plus
  the existing context test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant