Backend User Login Flow and Token Management with Spring and Redis
This article explains a complete backend user login process, including phone verification, token generation, token expiration strategies, gateway token validation, logout handling, anonymous request options, blacklist management, and provides a Spring‑Redis implementation for request‑rate limiting.
Introduction
The article introduces the user login process and its technical implementation, covering user authentication, how to obtain user information, and special cases such as blacklist handling and anonymous requests that bypass verification.
Business Diagram
The login flow involves both client‑side actions (phone number entry, verification code sending, code entry, optional auto‑registration) and server‑side validation (code verification, user existence check, token generation, token return).
Process Explanation
Client side typically uses mobile phone verification code login.
Enter phone number
Send verification code
Enter verification code
Check "auto‑register new user" if applicable
Server side validates the code, checks user existence (creates a new user if absent), generates a token, and returns it to the client.
User Information Design
Verification Flow Diagram
The verification process uses two APIs and two caches:
Get Verification Code API : Sends a code to the phone number and stores it in a cache with an expiration time.
Login API : Receives phone number and code, checks the cache, and on success generates a token that the client uses for subsequent requests.
About Token Expiration Time
Token lifetimes differ by client type: mobile apps typically receive a week‑long token, while web tokens expire after a few hours. Separate endpoints or header inspection can be used to apply different expiration policies.
About Business Request Token Verification
After login, each client request carries the token. A gateway validates the token, retrieves cached user basic information, and injects user ID, account, and nickname into request headers for downstream services.
About Logout Operation
The client calls a logout API; the server deletes the token’s cache entry and returns a 401 response, prompting the client to redirect to the login page.
About Anonymous Requests (No Login)
Two common approaches allow anonymous access:
Authorized token with a request‑rate limit.
Path‑based whitelist using regular‑expression matching in the gateway.
Scheme 1: Authorized Token with Rate Limiting
This method tracks request counts per token, allowing traceability while preventing abuse; it requires additional coding and configuration.
Technical Implementation
Provide a management page for authorized tokens, specifying token value and allowed requests per time unit (e.g., 60 per minute).
Implement CRUD operations to store tokens in a cache (using a map where the key is the token and the value is the request limit).
Use a cache with a one‑minute expiration to count requests.
The verification flow diagram is then extended to include rate‑limit checks.
Request Count Check Code Implementation
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* Authorized token request‑limit cache
*/
@Component
public class AuthTokenRequestLimitCache {
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
private static final String AUTH_TOKEN_LIMIT_KEY_PREFIX = "auth_token_limit";
/**
* Increment request count and check if it exceeds the limit
* @param token
* @return whether the request is allowed
*/
public boolean incrementWithCheck(String token) {
// 1. Get the configured limit; null means the token is no longer authorized
Integer limit = getLimit(token);
if (limit == null) {
return false;
}
// 2. Build cache key and read current count
String key = String.join(":", AUTH_TOKEN_LIMIT_KEY_PREFIX, token);
Integer count = redisTemplate.opsForValue().get(key);
// 3. If no count exists, initialize it and set a 1‑minute TTL
if (count == null) {
redisTemplate.opsForValue().increment(key);
redisTemplate.expire(key, 1L, TimeUnit.MINUTES);
return true;
}
// Increment and compare with limit; if exceeded, gateway can reject the request
Long inc = redisTemplate.opsForValue().increment(key);
return inc <= limit;
}
/**
* Retrieve the request limit for a token
* @param token
* @return limit value or null
*/
public Integer getLimit(String token) {
Object limit = redisTemplate.opsForHash().get("auth_token_limit", token);
return limit == null ? null : (Integer) limit;
}
}Typically, only GET operations are allowed on the authorized token endpoint; data‑modifying actions are usually prohibited.
Scheme 2: Request Path Regex Validation
Configure the gateway with regex rules for anonymous endpoints; matching requests bypass token verification, while others undergo normal authentication.
About Blacklist
Blacklist handling adds a final security layer:
Admin UI provides a “block user” button; blocked user IDs are stored in a Redis set.
During login, the system checks the blacklist and rejects blocked users.
If a logged‑in user is later blocked, the gateway removes the associated token cache and returns 401, forcing the client to re‑login.
Conclusion
The user system is a fundamental component; this article gives developers a comprehensive view of login workflows, token management, rate limiting, anonymous access, and blacklist strategies, enabling them to design and implement robust authentication services.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
