# indie-framework **Repository Path**: noodle-framework/indie-framework ## Basic Information - **Project Name**: indie-framework - **Description**: ε°θ£…δΌδΈšspring-boot-starter - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-10-15 - **Last Updated**: 2026-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Indie Framework > An enterprise-grade foundational framework built on Spring Boot 3 + JDK 17, offering a rich set of Starter modules to > streamline development and boost productivity. ## Introduction Indie Framework is a modular Spring Boot framework that encapsulates commonly used components in enterprise application development. Through the Starter pattern, developers can selectively import only the modules they need, enabling rapid construction of high-quality applications. ### Key Features - πŸ“¦ **Modular Design** β€” Import on demand, combine flexibly - πŸš€ **Out of the Box** β€” Auto-configuration, zero-code integration - ☁️ **Multi-Cloud Support** β€” Alibaba Cloud, Tencent Cloud, Huawei Cloud, Qiniu Kodo, MinIO, RustFS - πŸ”’ **Built-in Security** β€” JWT authentication, Spring Security, config encryption - πŸ›‘οΈ **Enterprise Enhancements** β€” Audit logging, soft delete, multi-tenancy, sensitive data masking ## Requirements | Dependency | Version | |-------------|---------| | JDK | 17+ | | Spring Boot | 3.5.x | | Maven | 3.6+ | ## Modules All starters share the groupId `cn.indie.framework` and the `indie-spring-boot-starter-*` artifactId prefix. Aggregator modules (captcha / persist / security / sms / store) are `pom`-packaging build parents β€” depend on the leaf artifacts listed below them, not on the aggregators. ### Core & Utilities | Module | Description | |-------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| | `indie-spring-boot-starter-core` | Core module β€” `ApiResult`, `Catchable` exception contract, ticket model, `Snowflake`, `StoreKey` | | `indie-spring-boot-starter-jackson` | JSON processing based on Jackson β€” sensitive data masking, dictionary translation | | `indie-spring-boot-starter-web` | Web MVC enhancement β€” MDC tracing, repeatable request body (no CORS: cross-origin headers are handled by the fronting nginx) | | `indie-spring-boot-starter-guard` | Transport-agnostic admission kernel β€” debounce / rate-limit / replay / idempotency engines, stores and `SignatureUtils` (no Spring auto-configuration) | ### HTTP Clients | Module | Description | |---------------------------------------|------------------------------------------------| | `indie-spring-boot-starter-http` | HTTP client based on RestTemplate (`HttpOps`) | | `indie-spring-boot-starter-webclient` | WebClient support β€” reactive HTTP client | | `indie-spring-boot-starter-okhttp` | HTTP client based on OkHttp (sync `OkHttpOps`) | ### Data Access | Module | Description | |-------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `indie-spring-boot-starter-persist-core` | Persistence common core: audit/tenant capability interfaces and shared auditor, tenant, cursor-pagination support classes | | `indie-spring-boot-starter-persist-jpa` | JPA support β€” auditing, soft delete, multi-tenancy | | `indie-spring-boot-starter-persist-mybatisplus` | MyBatis-Plus support β€” auto-fill, logical delete, tenant isolation | | `indie-spring-boot-starter-excel` | Excel operations based on FastExcel (`ExcelOps`) | | `indie-spring-boot-starter-qrcode` | QR code generation based on ZXing (`QRCodeOps`) | | `indie-spring-boot-starter-lifter` | Reactive context propagation (opt-in) β€” lifts ticket / MDC from the Reactor Context into ThreadLocals; enabled per feature via `indie.framework.lifter.features: [ticket, mdc]` | > ⚠️ **Note**: The persistence modules require entity tables to have a numeric primary key field named `id` > (auto-increment / snowflake ID) for auditing, tenant isolation and cursor pagination. ### Cache & Traffic Governance | Module | Description | |---------------------------------------|---------------------------------------------------------------------------| | `indie-spring-boot-starter-redis` | Distributed caching based on Redis with rich operation APIs (`RedisOps`) | | `indie-spring-boot-starter-ratelimit` | Annotation-based rate limiting (`@RateLimit`), local or Redis-backed | | `indie-spring-boot-starter-debounce` | Anti-duplicate-submission protection (`@Debounce`), local or Redis-backed | | `indie-spring-boot-starter-idempotent` | Business idempotency (`@Idempotent`) β€” replay or reject duplicate submissions keyed by an `Idempotency-Key` header, local or Redis-backed | > `debounce` suppresses accidental double-submits within a short window (by IP / user); `idempotent` suppresses > **business** duplicate submissions keyed by a client-supplied `Idempotency-Key` header (window up to 24h), replaying > or rejecting the repeat. Both share the transport-agnostic `guard` kernel and have no module-level on/off switch β€” > annotate the endpoint to enable. The gateway exposes the same capability via `features: [idempotent]`. > Replay also covers async endpoints (`Callable` / `DeferredResult`); the response copy is captured on the `ASYNC` > dispatch, and both the completion and the failure-release transitions are guarded by the holder token. ### Security & Authentication | Module | Description | |----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `indie-spring-boot-starter-jwt` | JWT issuing & verification (`JwtOps`); `@JwtClaim` marks **ticket fields** that become claims (FIELD/METHOD only, no parameter injection) | | `indie-spring-boot-starter-security-core` | Shared security configuration (`SecurityProperties`) and utilities β€” `TicketAuthenticationToken`, header/auth validators, password utilities (no auto-configuration of its own) | | `indie-spring-boot-starter-security-servlet` | Spring Security integration for Servlet (Spring MVC) server applications | | `indie-spring-boot-starter-security-reactor` | Spring Security integration for WebFlux (reactive) server applications | | `indie-spring-boot-starter-signature` | API signature verification + timestamp anti-replay (`@Signature`) | | `indie-spring-boot-starter-captcha-graphic` | Behavioral CAPTCHA β€” slide / rotate / curve / spatial-reasoning challenges (`GraphicOps`) | | `indie-spring-boot-starter-captcha-axet` | Text / math CAPTCHA (`AxetOps`) | | `indie-spring-boot-starter-jasypt` | Configuration file encryption | > `security-servlet` and `security-reactor` are mutually exclusive β€” pick the one matching your server stack. > Both work with the `jwt` module, which handles token issuing and verification. > > Method-level security (`@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, `@PostFilter`) is enabled by default on > both stacks β€” no `@EnableMethodSecurity` required. Servlet additionally supports `@Secured` and JSR-250 > (`@RolesAllowed` / `@PermitAll` / `@DenyAll`), which have no reactive counterpart in Spring Security. ### Object Storage | Module | Description | |------------------------------------------|------------------------------------------------------------| | `indie-spring-boot-starter-store-core` | Unified `AwsStore` SPI + key guard (multi-tenant aware) | | `indie-spring-boot-starter-store-minio` | MinIO object storage support | | `indie-spring-boot-starter-store-oss` | Alibaba Cloud OSS support | | `indie-spring-boot-starter-store-cos` | Tencent Cloud COS support | | `indie-spring-boot-starter-store-rustfs` | RustFS object storage support | | `indie-spring-boot-starter-store-obs` | Huawei Cloud OBS support (official `esdk-obs-java-bundle`) | | `indie-spring-boot-starter-store-kodo` | Qiniu Kodo support (official `qiniu-java-sdk`) | > Import one vendor starter β€” it transitively brings `store-core`. Inject the unified `AwsStore` interface when only one > implementation is on the classpath; inject the concrete type (e.g. `CosAwsStore`) when several are present. > > `AbstractAwsStore` is an **S3-semantics template, not an AWS-SDK template** β€” its 13 abstract hooks reference no SDK > types. Vendor selection follows "is the vendor's own SDK the first-class citizen?": providers whose only surface is > an S3-compatible layer (RustFS) reuse AWS SDK v2; providers whose official SDK speaks a proprietary protocol use > that SDK β€” Huawei Cloud OBS uses `esdk-obs-java-bundle`, and **Qiniu Kodo uses the official `qiniu-java-sdk`**. ### Messaging & Notification | Module | Description | |-------------------------------------------------|-----------------------------------------------------------------------------| | `indie-spring-boot-starter-email` | Email support β€” plain text, HTML, attachments | | `indie-spring-boot-starter-sms-core` | SMS SPI & resilience β€” retry / degradation / rate-limit, multi-tenant aware | | `indie-spring-boot-starter-sms-aliyun-domestic` | Aliyun SMS β€” domestic channel | | `indie-spring-boot-starter-sms-aliyun-globe` | Aliyun SMS β€” international channel | | `indie-spring-boot-starter-sms-tencent` | Tencent Cloud SMS | | `indie-spring-boot-starter-sse` | Server-Sent Events support | | `indie-spring-boot-starter-wechat` | WeChat login: mini-program / OAuth2 / PC QR-code login | > SMS vendor starters transitively bring `sms-core` (and `sms-aliyun-core` for Aliyun). The SPI is extensible to other > providers such as Huawei Cloud or Qiniu. ### Gateway Enhancements | Module | Description | |-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------| | `indie-spring-boot-starter-gateway` | Gateway enhancements for Spring Cloud Gateway / WebFlux β€” rate limiting, signature, anti-replay, anti-abuse, idempotency, circuit breaking, gray routing | ### API Documentation | Module | Description | |-------------------------------------|----------------------------------------------| | `indie-spring-boot-starter-swagger` | API documentation based on SpringDoc OpenAPI | ## Quick Start ### 1. Import Dependency Management Import the Indie Framework BOM in your `pom.xml` for centralized version control: ```xml cn.indie.framework indie-framework-dependencies ${last.version} pom import ``` ### 2. Add Required Modules Add the Starter modules you need. For example, to use the core and web modules: ```xml cn.indie.framework indie-spring-boot-starter-core cn.indie.framework indie-spring-boot-starter-web ``` ### 3. Configure and Use Each module includes corresponding auto-configuration and property classes. Enable and configure features by setting the relevant properties in `application.yml` or `application.properties`. ## Security Best Practices ### XSS Protection Combination (Important) The framework follows the opt-in principle: both XSS-related switches are **disabled by default**. If neither is enabled, the application has zero protection against stored XSS. Enable them explicitly as recommended below: | Layer | Property / API | Default | Description | |-------------------------------------|--------------------------------------------|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| | Output layer (primary, recommended) | `indie.framework.security.csp.enabled` | `false` | The `security` module emits the `Content-Security-Policy` response header to block script injection in browsers | | Input layer (optional, auxiliary) | `JsonOps.xss()` / `JsonOps.xss(sanitizer)` | not applied | HTML-escapes strings **only** for deserialization performed through that call-scoped mapper β€” there is **no** `indie.framework.jackson.xss-enabled` switch | **Recommendations:** 1. **Defend at the rendering/output layer first**: template engines (Thymeleaf / FreeMarker) HTML-escape variables by default; in frontend-backend separated apps, frontend frameworks (React / Vue) handle escaping β€” this is the correct XSS defense line. 2. **Enable the CSP response header** (requires `indie-spring-boot-starter-security-servlet` or `indie-spring-boot-starter-security-reactor`): ```yaml indie: framework: security: csp: enabled: true # The default policy already includes default-src 'self'; script-src 'self'; # frame-ancestors 'none', etc. Override policy-directives only if you need # to allow CDNs or other origins. ``` 3. **Be cautious with the input-layer escaping** (`JsonOps.xss()`): it HTML-escapes every deserialized string before persistence, **irreversibly corrupting** any legitimate content containing `<...>` (code, math expressions, XML, Markdown). Ingestion paths bypassing Jackson (SQL imports, message queues) are not covered at all, so it cannot provide real protection on its own. It is also **not a global setting** β€” it only applies where you explicitly serialize through `JsonOps.xss()`, so enable it only when an input-layer fallback is truly required. > ⚠️ A misconfigured CSP may break parts of your pages (inline scripts, third-party resources). > Test thoroughly before enabling. ### Outbound Request Target Validation (Important) `http` / `okhttp` / `webclient` send the target address **as given** β€” they perform no target-address validation beyond the protocol, and never check whether the target points at an internal host, the loopback interface, or a cloud metadata endpoint. When a request address comes from user input or external data (webhook callbacks, image proxies, URL previews, file fetching), the application **must validate it before calling**, otherwise the request can be steered to internal services or cloud metadata endpoints (SSRF). The framework supplies a pure predicate, `Outbounds.isPublic(URI)`: - Only `http` and `https` are accepted. - An address literal is judged directly, with no name-service round trip. - A hostname is resolved and **every** result is judged; if any result falls in a non-public range, or the name cannot be resolved, the target is rejected (fail-closed). It is a tool, not a defense line: it only works where you call it, and it does not remove the two residual gaps β€” DNS rebinding between validation and connection, and **redirect following**. The latter must be handled alongside it: allowing the initial address says nothing about where a redirect leads (`http` / `okhttp` expose `follow-redirects`, `webclient` does not follow redirects at all). ## Project Structure ``` indie-framework β”œβ”€β”€ indie-framework-dependencies # BOM (dependency version management) β”œβ”€β”€ indie-spring-boot-starter-core # Core β”œβ”€β”€ indie-spring-boot-starter-jackson # JSON processing β”œβ”€β”€ indie-spring-boot-starter-web # Web MVC β”œβ”€β”€ indie-spring-boot-starter-http # HTTP client (RestTemplate) β”œβ”€β”€ indie-spring-boot-starter-webclient # HTTP client (WebClient) β”œβ”€β”€ indie-spring-boot-starter-okhttp # HTTP client (OkHttp) β”œβ”€β”€ indie-spring-boot-starter-excel # Excel β”œβ”€β”€ indie-spring-boot-starter-qrcode # QR code β”œβ”€β”€ indie-spring-boot-starter-lifter # Reactive context propagation (opt-in) β”œβ”€β”€ indie-spring-boot-starter-redis # Redis cache β”œβ”€β”€ indie-spring-boot-starter-guard # Admission engines (rate limit / debounce / replay) β”‚ # shared skeleton: cn.indie.framework.guard β”‚ # (.debounce / .ratelimit / .signature) β”œβ”€β”€ indie-spring-boot-starter-ratelimit # Rate limiting (@RateLimit), Spring MVC β”œβ”€β”€ indie-spring-boot-starter-debounce # Debounce (@Debounce), Spring MVC β”œβ”€β”€ indie-spring-boot-starter-signature # Signature verification (@Signature), Spring MVC β”œβ”€β”€ indie-spring-boot-starter-jwt # JWT authentication β”œβ”€β”€ indie-spring-boot-starter-jasypt # Config encryption β”œβ”€β”€ indie-spring-boot-starter-swagger # API docs β”œβ”€β”€ indie-spring-boot-starter-wechat # WeChat login (mini-program / OAuth2 / PC QR-code login) β”œβ”€β”€ indie-spring-boot-starter-gateway # Gateway enhancements β”œβ”€β”€ indie-spring-boot-starter-captcha # CAPTCHA aggregator β”‚ β”œβ”€β”€ indie-spring-boot-starter-captcha-graphic # Behavioral CAPTCHA (slide / rotate / curve / spatial) β”‚ └── indie-spring-boot-starter-captcha-axet # Text / math CAPTCHA β”œβ”€β”€ indie-spring-boot-starter-persist # Persistence aggregator β”‚ β”œβ”€β”€ indie-spring-boot-starter-persist-core # Persistence common core β”‚ β”œβ”€β”€ indie-spring-boot-starter-persist-jpa # JPA data access β”‚ └── indie-spring-boot-starter-persist-mybatisplus # MyBatis-Plus β”œβ”€β”€ indie-spring-boot-starter-security # Security aggregator β”‚ β”œβ”€β”€ indie-spring-boot-starter-security-core # Security core abstractions β”‚ β”œβ”€β”€ indie-spring-boot-starter-security-servlet # Spring MVC integration β”‚ └── indie-spring-boot-starter-security-reactor # WebFlux integration β”œβ”€β”€ indie-spring-boot-starter-sms # SMS aggregator β”‚ β”œβ”€β”€ indie-spring-boot-starter-sms-core # SMS SPI & resilience β”‚ β”œβ”€β”€ indie-spring-boot-starter-sms-aliyun # Aliyun SMS aggregator β”‚ β”‚ β”œβ”€β”€ indie-spring-boot-starter-sms-aliyun-core # Shared base β”‚ β”‚ β”œβ”€β”€ indie-spring-boot-starter-sms-aliyun-domestic # Domestic channel β”‚ β”‚ └── indie-spring-boot-starter-sms-aliyun-globe # International channel β”‚ └── indie-spring-boot-starter-sms-tencent # Tencent Cloud SMS └── indie-spring-boot-starter-store # Object storage aggregator β”œβ”€β”€ indie-spring-boot-starter-store-core # Unified AwsStore SPI β”œβ”€β”€ indie-spring-boot-starter-store-minio # MinIO β”œβ”€β”€ indie-spring-boot-starter-store-oss # Alibaba Cloud OSS β”œβ”€β”€ indie-spring-boot-starter-store-cos # Tencent Cloud COS β”œβ”€β”€ indie-spring-boot-starter-store-rustfs # RustFS β”œβ”€β”€ indie-spring-boot-starter-store-obs # Huawei Cloud OBS └── indie-spring-boot-starter-store-kodo # Qiniu Kodo ``` ## License This project is licensed under the [Apache License 2.0](./LICENSE).