# 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).