Skip to content

Commit 10e0f98

Browse files
FdHerrerasjohnr
authored andcommitted
Add doc and javadoc for CachingUserDetailsService
Close gh-10914
1 parent 5ad34d1 commit 10e0f98

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

core/src/main/java/org/springframework/security/authentication/CachingUserDetailsService.java

+49
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,55 @@
2323
import org.springframework.util.Assert;
2424

2525
/**
26+
* Implementation of {@link UserDetailsService} that utilizes caching through a
27+
* {@link UserCache}
28+
* <p>
29+
* If a null {@link UserDetails} instance is got from calling
30+
* {@link UserCache#getUserFromCache(String)} to the {@link UserCache} got from
31+
* {@link #getUserCache()}, the user load is deferred to the {@link UserDetailsService}
32+
* provided during construction. Otherwise, the instance got from cache is returned.
33+
* <p>
34+
* It is initialized with a {@link NullUserCache} by default, so it's strongly recommended
35+
* setting your own {@link UserCache} using {@link #setUserCache(UserCache)}, otherwise,
36+
* the delegate will be called every time.
37+
* <p>
38+
* Utilize this class by defining {@link org.springframework.context.annotation.Bean} that
39+
* encapsulates an actual implementation of {@link UserDetailsService} and set an
40+
* {@link UserCache}.
41+
* </p>
42+
* For example: <pre>{@code
43+
* &#64;Bean
44+
* public CachingUserDetailsService cachingUserDetailsService(UserDetailsService delegate,
45+
* UserCache userCache) {
46+
* CachingUserDetailsService service = new CachingUserDetailsService(delegate);
47+
* service.setUserCache(userCache);
48+
* return service;
49+
* }
50+
* }</pre>
51+
*
52+
* <p>
53+
* However, a preferable approach would be to use
54+
* {@link org.springframework.cache.annotation.Cacheable} in your
55+
* {@link UserDetailsService#loadUserByUsername(String)} implementation to cache
56+
* {@link UserDetails} by <code>username</code>, reducing boilerplate and setup, specially
57+
* if you are already using cache in your application.
58+
* </p>
59+
*
60+
* For example:
61+
*
62+
* <pre>{@code
63+
* &#64;Service
64+
* public class MyCustomUserDetailsImplementation implements UserDetailsService {
65+
66+
* &#64;Override
67+
* &#64;Cacheable
68+
* public UserDetails loadUserByUsername(String username) {
69+
* //some logic here to get the actual user details
70+
* return userDetails;
71+
* }
72+
* }
73+
* }</pre>
74+
*
2675
* @author Luke Taylor
2776
* @since 2.0
2877
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[[servlet-authentication-cached]]
2+
= CachingUserDetailsService
3+
4+
Spring Security's `CachingUserDetailsService` implements xref:servlet/authentication/passwords/user-details-service.adoc#servlet-authentication-userdetailsservice[UserDetailsService] offering support for caching authentication.
5+
6+
`CachingUserDetailsService` provides caching support for `UserDetails` by delegating the authentication process to the provided `UserDetailsService`. The result is then stored in a `UserCache` to reduce computation in subsequent calls.
7+
8+
Utilize this class by defining a `@Bean` of it that encapsulates a concrete implementation of `UserDetailsService` and set a `UserCache` to cache authenticated `UserDetails`.
9+
10+
For example:
11+
12+
[source,java]
13+
----
14+
@Bean
15+
public CachingUserDetailsService cachingUserDetailsService(UserDetailsService delegate, UserCache userCache) {
16+
CachingUserDetailsService service = new CachingUserDetailsService(delegate);
17+
service.setUserCache(userCache);
18+
return service;
19+
}
20+
----
21+
22+
However, a preferable approach would be to use `@Cacheable` in your `UserDetailsService.loadUserByUsername(String)` implementation to cache `UserDetails` by `username`, reducing boilerplate and setup, especially if you are already using cache in your application.
23+
24+
For example:
25+
26+
[source,java]
27+
----
28+
@Service
29+
public class MyCustomUserDetailsImplementation implements UserDetailsService {
30+
31+
@Override
32+
@Cacheable
33+
public UserDetails loadUserByUsername(String username) {
34+
// some logic here to get the actual user details
35+
return userDetails;
36+
}
37+
}
38+
----

docs/modules/ROOT/pages/servlet/authentication/passwords/user-details-service.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
= UserDetailsService
33

44
{security-api-url}org/springframework/security/core/userdetails/UserDetailsService.html[`UserDetailsService`] is used by xref:servlet/authentication/passwords/dao-authentication-provider.adoc#servlet-authentication-daoauthenticationprovider[`DaoAuthenticationProvider`] for retrieving a username, a password, and other attributes for authenticating with a username and password.
5-
Spring Security provides xref:servlet/authentication/passwords/in-memory.adoc#servlet-authentication-inmemory[in-memory] and xref:servlet/authentication/passwords/jdbc.adoc#servlet-authentication-jdbc[JDBC] implementations of `UserDetailsService`.
5+
Spring Security provides xref:servlet/authentication/passwords/in-memory.adoc#servlet-authentication-inmemory[in-memory], xref:servlet/authentication/passwords/jdbc.adoc#servlet-authentication-jdbc[JDBC], and xref:servlet/authentication/passwords/cached.adoc#servlet-authentication-cached[in-cache] implementations of `UserDetailsService`.
66

77
You can define custom authentication by exposing a custom `UserDetailsService` as a bean.
88
For example, the following listing customizes authentication, assuming that `CustomUserDetailsService` implements `UserDetailsService`:

0 commit comments

Comments
 (0)