What kind of Ethereal Wind blew you in🍃!
Come on in and see if anything catches your eye, my dear friend😉.
Come on in and see if anything catches your eye, my dear friend😉.
The TCP Three-Way Handshake Client — Server Purpose of the three-way handshake: the client’s send and receive are both fine, and the server’s send and receive are both fine. First handshake: the client sends SYN (synchronize request) Client: I know nothing, so I’ll send out a SYN message and see if anyone receives it. If no one replies, I send it a few more times (timeout retransmission). At this moment, what the client knows is: I sent it, but I don’t know whether anyone received it ❌ Can I receive messages? Unknown ❌ Does the other side exist? Unknown ❌ Second handshake: the server replies SYN+ACK (synchronize + acknowledge) The server received the client’s SYN. ...
The Normal JWT Request Flow sequenceDiagram participant User as User participant Frontend as Frontend (browser/app) participant Auth as Auth server participant Backend as Backend API server Note over User,Backend: 1. Login phase User->>Frontend: enter username/password Frontend->>Auth: POST /login (credentials) Auth->>Auth: verify credentials Auth-->>Frontend: return access_token + refresh_token Frontend->>Frontend: store tokens (memory/localStorage) Frontend-->>User: login successful Note over User,Backend: 2. Normal request phase User->>Frontend: request a protected resource Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: verify access_token signature and expiry Backend-->>Frontend: return the requested resource Frontend-->>User: display data Note over User,Backend: 3. Access token expires User->>Frontend: keep requesting Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token (expired) Backend-->>Frontend: 401 Unauthorized (token expired) Frontend->>Frontend: detects 401, triggers refresh logic Note over Frontend,Auth: 4. Token refresh phase Frontend->>Auth: POST /refreshrefresh_token Auth->>Auth: verify refresh_token Auth-->>Frontend: return a new access_token (optionally a new refresh_token) Frontend->>Frontend: update the stored access_token Frontend->>Backend: retry the original request (new access_token) Backend-->>Frontend: return the requested resource Frontend-->>User: display data Why You Can’t Rely on JWT Alone Once a refresh token is issued and the backend doesn’t store it, it becomes an uncontrollable long-term pass You can’t forcibly log a user out You can’t log out a single device You can’t tell whether a token has been stolen (an attacker who gets the refresh token can keep refreshing the access token forever) You can’t implement session management The Flow After Using a refresh_tokens Table sequenceDiagram participant User as User participant Frontend as Frontend participant Auth as Auth server participant DB as Database (refresh_tokens table) participant Backend as Backend API server Note over User,DB: 1. Login phase (issue token + persist) User->>Frontend: enter username/password Frontend->>Auth: POST /login Auth->>Auth: verify credentials Auth->>DB: generate a unique refresh_token_idINSERT INTO refresh_tokens(user_id, token_hash, expires_at, device_info, ip_address, revoked) DB-->>Auth: insert successful Auth->>Auth: generate access_token + refresh_token(refresh_token contains the id reference) Auth-->>Frontend: return access_token + refresh_token Frontend->>Frontend: store tokens Frontend-->>User: login successful Note over User,Backend: 2. Normal request (same as before) User->>Frontend: request a resource Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: verify access_token Backend-->>Frontend: return the resource Note over Frontend,DB: 3. Access token expires → refresh Frontend->>Backend: GET /api/resource (access_token expired) Backend-->>Frontend: 401 Unauthorized Frontend->>Auth: POST /refreshrefresh_token Note over Auth,DB: 4. Refresh verification (multi-step checks) Auth->>Auth: parse refresh_token, extract token_id Auth->>DB: SELECT * FROM refresh_tokensWHERE id = token_id DB-->>Auth: return the record Auth->>Auth: verification checklist: Note over Auth: ✅ does token_hash match✅ is it expired (expires_at > now())✅ is it revoked (revoked = false)✅ is the user still valid✅ does device info match (optional) alt all checks pass Auth->>DB: UPDATE refresh_tokensSET last_used_at = now(), last_used_ip = current_ipWHERE id = token_id Auth->>Auth: generate a new access_token(optional: extend refresh_token validity) Auth-->>Frontend: return the new access_token Frontend->>Frontend: update access_token Frontend->>Backend: retry the original request (new token) Backend-->>Frontend: return the resource else checks fail Auth-->>Frontend: 401/403 (refresh failed) Frontend->>Frontend: clear all tokens Frontend->>User: redirect to the login page end Note over User,DB: 5. Explicit logout User->>Frontend: click logout Frontend->>Auth: POST /logoutrefresh_token Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE id = token_id Auth-->>Frontend: logout successful Frontend->>Frontend: clear local tokens Frontend-->>User: logged out Note over User,DB: 6. Security scenario: password change User->>Frontend: change password Frontend->>Auth: POST /change-password Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE user_id = current_user_id Note over DB: revoke all of the user's refresh_tokens(force all devices to log in again) Auth-->>Frontend: password change successful Frontend->>Frontend: clear local tokens Frontend-->>User: please log in again
Data source: Spring Cloud Alibaba official Wiki After Spring Boot 3.3.4 Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2025.1.0.0 2025.1.0 4.0.0 Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2025.0.0.0 2025.0.0 3.5.0 Component version relationships The component versions each Spring Cloud Alibaba release is compatible with are shown below: Spring Cloud Alibaba Version Sentinel Version Nacos Version RocketMQ Version SchedulerX Version Seata Version 2025.1.0.0 1.8.9 3.1.1 5.3.1 1.13.3 2.5.0 2025.0.0.0 1.8.9 3.0.3 5.3.1 1.13.1 2.5.0 Importing the dependencies <dependencyManagement> <dependencies> <!-- Unified Spring Boot version management --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.5.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Official Spring Cloud version management --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2025.0.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Unified Spring Cloud Alibaba (Alibaba ecosystem) version --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2025.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> Spring Boot 3.3.4 and earlier 📌 New versions (Calendar Versioning, recommended) Spring Cloud Alibaba Spring Cloud Spring Boot 2023.0.3.2 2023.0.3 3.3.4 2023.0.3.0 2023.0.3 3.3.4 2023.0.1.0 2023.0.1 3.2.4 2023.0.0.0-RC1 2023.0.0 3.2.0 2022.0.0.0 2022.0.0 3.0.2 2022.0.0.0-RC2 2022.0.0-RC2 3.0.2 2022.0.0.0-RC1 2022.0.0-RC1 3.0.0 2021.0.6.2 2021.0.9 2.7.18 2021.0.6.0 2021.0.9 2.7.18 2021.0.5.0 2021.0.5 2.6.13 2021.0.4.0 2021.0.4 2.6.11 2021.0.1.0 2021.0.1 2.6.3 2021.1 2020.0.1 2.4.2 📌 Old versions (RELEASE naming) Spring Cloud Alibaba Spring Cloud Spring Boot 2.2.10.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.9.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.8.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.7.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.6.RELEASE Hoxton.SR9 2.3.2.RELEASE 2.2.1.RELEASE Hoxton.SR3 2.2.5.RELEASE 2.2.0.RELEASE Hoxton.RELEASE 2.2.X.RELEASE 2.1.4.RELEASE Greenwich.SR6 2.1.13.RELEASE 2.1.2.RELEASE Greenwich 2.1.X.RELEASE 2.0.4.RELEASE ⛔ Finchley 2.0.X.RELEASE 1.5.1.RELEASE ⛔ Edgware 1.5.X.RELEASE ⛔ means maintenance has stopped ...
Tech stack: Spring Boot 3 · Spring Cloud Alibaba · OpenFeign · JWT · Gateway · Nacos How to use this document When you talk about a project in an interview, the worst thing you can do is start from code details. The right order is: First explain what problem it solves → then the overall architecture → then walk through it by request flow → finally handle the deep-dive questions. ...
Everyone who has written a backend, sooner or later, has to fight a hard battle with “login.” It looks like a small feature — a username, a password, a button — but anyone who has actually built it knows this is the part of the whole system with the deepest pits, the most painful changes, and the most fatal failures. It’s a hassle not because the technology is hard, but because it sits right at the intersection of three parties’ interests: users want convenience, product wants growth, and security wants an airtight defense. These three are naturally at odds. Every inch you move toward one, the other two start crying out. ...
General Dependency management Pinning all three versions in the parent pom.xml Version reference <dependencyManagement> <dependencies> <!-- 1. Spring Boot base version --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.5.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 2. Spring Cloud cloud-native base --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2025.0.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 3. Spring Cloud Alibaba full dependency core (key!) --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2025.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> Main class @MapperScan("asia.liminality.user.mapper") @SpringBootApplication @Slf4j public class UserApplication { public static void main(String[] args) throws UnknownHostException { ConfigurableApplicationContext app = SpringApplication.run(UserApplication.class, args); Environment env = app.getEnvironment(); String protocol = "http"; if (env.getProperty("server.ssl.key-store") != null) { protocol = "https"; } log.info("--/\n---------------------------------------------------------------------------------------\n\t" + "Application '{}' is running! Access URLs:\n\t" + "Local: \t\t{}://localhost:{}\n\t" + "External: \t{}://{}:{}\n\t" + "Profile(s): \t{}" + "\n---------------------------------------------------------------------------------------", env.getProperty("spring.application.name"), protocol, env.getProperty("server.port"), protocol, InetAddress.getLocalHost().getHostAddress(), env.getProperty("server.port"), env.getActiveProfiles()); } } domain DTO Result import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class Result<T> { private int code; private String message; private T data; public static <T> Result<T> success(T data) { return new Result<>(200, "success", data); } public static <T> Result<T> success() { return new Result<>(200, "success", null); } public static <T> Result<T> failure(String message) { return new Result<>(500, message, null); } public static <T> Result<T> failure(int code, String message) { return new Result<>(code, message, null); } public static <T> Result<T> failure(String message, T data) { return new Result<>(500, message, data); } } Spring Cloud Gateway AuthGlobalFilter @Slf4j @RequiredArgsConstructor @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { private final JwtUtil jwtUtil; private static final List<String> WHITE_LIST = List.of( "/auth/user/login", "/auth/user/register" ); // Check whether it's in the whitelist private boolean isWhiteList(String path){ return WHITE_LIST.stream().anyMatch(path::startsWith); } private Mono<Void> reject(ServerWebExchange exchange){ exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getPath().toString(); if (isWhiteList(path)) { return chain.filter(exchange); } String token = request.getHeaders().getFirst("Authorization"); // Token is empty, deny access if( token == null || token.isEmpty() ){ return reject( exchange ); } // Verify the token try { Integer userId = jwtUtil.parseToken(token); // TODO put userId into the request header log.info("🚪 inject into request header"); } catch (Exception e) { return reject(exchange); } return chain.filter( exchange ); } // Filter priority; the smaller, the earlier @Override public int getOrder() { return -1; } }
September 22, Monday — Day 1: Sudden onset Woke up in the morning with a blocked feeling in the right ear; the left ear was normal. I assumed it was just ear congestion or possibly otitis media, something that would resolve on its own, so I didn’t pay much attention. September 23, Tuesday — Day 2 In addition to the blocked sensation, I noticed an echo when hearing external speech. I started to feel something was wrong, but I still didn’t think it was serious and prioritized work. ...
Java’s LocalDateTime and PostgreSQL’s time types “aren’t talking about the same kind of time.” First, get clear on PostgreSQL’s two time types TIMESTAMP → without time zone, just a bare time "2026-06-25 10:00:00" TIMESTAMPTZ → with time zone, stored internally as UTC, converted to the session time zone on query On the Java side LocalDateTime → no concept of a time zone, just a bare time ZonedDateTime → with time zone OffsetDateTime → with an offset (e.g. +08:00) Instant → a UTC timestamp Why the error happens The PostgreSQL JDBC driver (especially newer versions 42.x+) is very strict about type matching: ...
In the Spring Boot ecosystem, the annotations changed a great deal between Swagger 2.0 (typically using the Springfox dependency) and Swagger 3.0 (typically using the Springdoc-openapi dependency, based on the OpenAPI 3 spec). Below is a complete correspondence table of the common annotations in Swagger 2.0 vs. Swagger 3.0 (OpenAPI 3): 1. Core annotation correspondence table Description Swagger 2.0 annotation (io.swagger.annotations) Swagger 3.0 annotation (io.swagger.v3.oas.annotations) Notes Mark a controller class @Api(tags = "User API") @Tag(name = "User API") 3.0 removed the description attribute; use name uniformly Mark an API method @ApiOperation(value = "Get user") @Operation(summary = "Get user") In 3.0 value became summary Request/entity class @ApiModel(value = "User object") @Schema(description = "User object") 3.0 greatly simplified this; use @Schema uniformly Entity class property @ApiModelProperty(value = "Name") @Schema(description = "Name") As above, merged into @Schema Ignore a property @ApiModelProperty(hidden = true) @Schema(hidden = true) Ignore a whole class/method @ApiIgnore @Hidden For endpoints or parameters you don’t want exposed in docs 2. Request-parameter annotation correspondence table For method parameters (URL path parameters, query parameters, etc.), 3.0 introduced a more structured configuration: ...
Issue source: spring-cloud-alibaba#3931 Affected versions: spring-cloud-alibaba 2023.0.1.3+ 1. Problem Description In Spring Cloud Alibaba 2023.X, placing Nacos config (including extension-configs, shared-configs, etc.) in bootstrap.yml / bootstrap.properties causes the config center’s content to fail to load properly, even though the logs show the bootstrap file itself was read. Moving the same config to application.yml makes everything work again. 2. Root Cause flowchart TD A[bootstrap.yml is read] --> B{SCA version check} B -- 2023.0.1.2 and earlier --> C[✅ Nacos config center loads normally] B -- 2023.0.1.3 and later --> D[❌ extension-configs / shared-configs fail] D --> E[Root cause: SCA 2023.0.1.3 changed the config-load priority mechanism] E --> F[Nacos PropertySource registered in the bootstrap phase is overwritten or discarded by later steps] In short: SCA 2023.0.1.3 made a backward-incompatible internal change, causing the Nacos extension config in bootstrap.yml to be “dropped” in the loading chain, while config in application.yml takes the new path and is unaffected. ...