Table of contents
Open Table of contents
Article body
If I am going to do this, I might as well do it thoroughly and make the effort worthwhile!
Common questions: 1. Have you considered how traditional web applications validate requests? See the first section.
2. Have you thought carefully about the real advantages of tokens over sessions? See the brief summary.
3. What is the right way to use tokens? See the questions for consideration.
Part One: how do traditional web applications, from before frontend/backend separation, ensure that incoming requests are valid? Here, “valid” means authenticated by the server.
Common scenarios: 1. Developers do not implement any request validation at all. There is no security!
2. Developers consistently use sessions to validate requests. After successful login authentication, user information is stored in the session. For every request requiring permission checks, the relevant code retrieves information from the current session. If you store it in the session but do not use the session for access checks, what is the point? If the check succeeds, the request is valid; otherwise, direct the user to log in.
For the second scenario, Shiro automatically stores user information in its session, as shown below. Retrieve it with User user = (User) SecurityUtils.getSubject().getPrincipal().

For an article on the drawbacks of server-side sessions and reasons to use tokens, see here, or search technical forums for related articles.
Here is a brief summary of the online answers that I find convincing:
-
If sessions are stored in server memory, too many sessions will affect server performance.
-
If sessions are stored in server memory, sharing them among servers is difficult in a large distributed system. Solutions do exist; see the session chapter in the Chinese book In-Depth Analysis of Java Web Technologies.
-
Sessions and their session IDs can be stored in a database. Do not be misled by articles claiming that they can only be stored in memory, although memory is the usual choice. The client uses its session ID to locate the corresponding session in server memory or the database.
-
Tokens are generally placed in request headers. With separate frontends and backends, the server returns a token after successful authentication. In a Vue project, store this token in a global cookie, then use interceptors.request.use to attach it dynamically to every request.
-
Like sessions, tokens can be stored in a database and have an expiration time.
-
Tokens are more useful on mobile clients because mobile clients do not support cookies.
Questions to Consider: How Should Tokens Be Stored?
How does the server check whether the token in a request is the one returned to the client during login authentication?
-
Store the token value, creation time, and expiration time in a database. For each request, query and compare the token to decide whether it is valid. But this is little different from storing sessions in a database. Every request requires a database query, creating substantial load when requests are numerous. Expired tokens must also be deleted periodically. If it is this inconvenient, why use it?
-
Store the token value, creation time, and expiration time in Redis. Redis can handle a high request volume and supports key expiration, solving both problems above. But the same solution works for sessions, so why use tokens? Sessions also have distributed solutions. We should not use tokens merely for their own sake—what makes them better?
-
Do not store tokens in either a cache or a database. Their most important advantage over sessions should be reduced server load, whether in memory or database usage. The rough idea is: after successful login authentication, return an encrypted token to the client. The encryption algorithm is crucial. Combine some user information with the request URL and a timestamp, then return the result to the client. On the next request, generate another token from the URL, timestamp, and user information, and compare it with the client’s token. If they match, the request is valid. Tokens then occupy no storage, and encryption/decryption is much faster than database queries. See this article for further details.
With these points in mind, the purpose of tokens becomes clear.