Skip to content

Commit 702cc1d

Browse files
committed
Extract SecurityContextHolder Docs
Issue gh-8005
1 parent 5e9c03a commit 702cc1d

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
[[servlet-authentication-securitycontextholder]]
2+
= SecurityContextHolder
3+
4+
:figures: images/servlet/authentication/architecture
5+
6+
At the heart of Spring Security's authentication model is the `SecurityContextHolder`.
7+
It contains the <<servlet-authentication-securitycontext>>.
8+
9+
image::{figures}/securitycontextholder.png[]
10+
11+
The `SecurityContextHolder` is where Spring Security stores the details of who is <<authentication,authenticated>>.
12+
Spring Security does not care how the `SecurityContextHolder` is populated.
13+
If it contains a value, then it is used as the currently authenticated user.
14+
15+
The simplest way to indicate a user is authenticated is to set the `SecurityContextHolder` directly.
16+
17+
.Setting `SecurityContextHolder`
18+
====
19+
[source,java]
20+
----
21+
SecurityContext context = SecurityContextHolder.createEmptyContext(); // <1>
22+
Authentication authentication =
23+
new TestingAuthenticationToken("username", "password", "ROLE_USER"); // <2>
24+
context.setAuthentication(authentication);
25+
26+
SecurityContextHolder.setContext(context); // <3>
27+
----
28+
====
29+
30+
<1> We start by creating an empty `SecurityContext`.
31+
It is important to create a new `SecurityContext` instance instead of using `SecurityContextHolder.getContext().setAuthentication(authentication)` to avoid race conditions across multiple threads.
32+
<2> Next we create a new <<servlet-authentication-authentication,`Authentication`>> object.
33+
Spring Security does not care what type of `Authentication` implementation is set on the `SecurityContext`.
34+
Here we use `TestingAuthenticationToken` because it is very simple.
35+
A more common production scenario is `UsernamePasswordAuthenticationToken(userDetails, password, authorities)`.
36+
<3> Finally, we set the `SecurityContext` on the `SecurityContextHolder`.
37+
Spring Security will use this information for <<authorization>>.
38+
39+
If you wish to obtain information about the authenticated principal, you can do so by accessing the `SecurityContextHolder`.
40+
41+
.Access Currently Authenticated User
42+
====
43+
[source,java]
44+
----
45+
SecurityContext context = SecurityContextHolder.getContext();
46+
Authentication authentication = context.getAuthentication();
47+
String username = authentication.getName();
48+
Object principal = authentication.getPrincipal();
49+
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
50+
----
51+
====
52+
53+
// FIXME: add links to HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal
54+
55+
By default the `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread of execution, even if the `SecurityContext` is not explicitly passed around as an argument to those methods.
56+
Using a `ThreadLocal` in this way is quite safe if care is taken to clear the thread after the present principal's request is processed.
57+
Spring Security's <<servlet-filterchainproxy,FilterChainProxy>> ensures that the `SecurityContext` is always cleared.
58+
59+
Some applications aren't entirely suitable for using a `ThreadLocal`, because of the specific way they work with threads.
60+
For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context.
61+
`SecurityContextHolder` can be configured with a strategy on startup to specify how you would like the context to be stored.
62+
For a standalone application you would use the `SecurityContextHolder.MODE_GLOBAL` strategy.
63+
Other applications might want to have threads spawned by the secure thread also assume the same security identity.
64+
This is achieved by using `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL`.
65+
You can change the mode from the default `SecurityContextHolder.MODE_THREADLOCAL` in two ways.
66+
The first is to set a system property, the second is to call a static method on `SecurityContextHolder`.
67+
Most applications won't need to change from the default, but if you do, take a look at the JavaDoc for `SecurityContextHolder` to learn more.

0 commit comments

Comments
 (0)