1 changed files with 67 additions and 0 deletions
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
[[servlet-authentication-securitycontextholder]] |
||||
= SecurityContextHolder |
||||
|
||||
:figures: images/servlet/authentication/architecture |
||||
|
||||
At the heart of Spring Security's authentication model is the `SecurityContextHolder`. |
||||
It contains the <<servlet-authentication-securitycontext>>. |
||||
|
||||
image::{figures}/securitycontextholder.png[] |
||||
|
||||
The `SecurityContextHolder` is where Spring Security stores the details of who is <<authentication,authenticated>>. |
||||
Spring Security does not care how the `SecurityContextHolder` is populated. |
||||
If it contains a value, then it is used as the currently authenticated user. |
||||
|
||||
The simplest way to indicate a user is authenticated is to set the `SecurityContextHolder` directly. |
||||
|
||||
.Setting `SecurityContextHolder` |
||||
==== |
||||
[source,java] |
||||
---- |
||||
SecurityContext context = SecurityContextHolder.createEmptyContext(); // <1> |
||||
Authentication authentication = |
||||
new TestingAuthenticationToken("username", "password", "ROLE_USER"); // <2> |
||||
context.setAuthentication(authentication); |
||||
|
||||
SecurityContextHolder.setContext(context); // <3> |
||||
---- |
||||
==== |
||||
|
||||
<1> We start by creating an empty `SecurityContext`. |
||||
It is important to create a new `SecurityContext` instance instead of using `SecurityContextHolder.getContext().setAuthentication(authentication)` to avoid race conditions across multiple threads. |
||||
<2> Next we create a new <<servlet-authentication-authentication,`Authentication`>> object. |
||||
Spring Security does not care what type of `Authentication` implementation is set on the `SecurityContext`. |
||||
Here we use `TestingAuthenticationToken` because it is very simple. |
||||
A more common production scenario is `UsernamePasswordAuthenticationToken(userDetails, password, authorities)`. |
||||
<3> Finally, we set the `SecurityContext` on the `SecurityContextHolder`. |
||||
Spring Security will use this information for <<authorization>>. |
||||
|
||||
If you wish to obtain information about the authenticated principal, you can do so by accessing the `SecurityContextHolder`. |
||||
|
||||
.Access Currently Authenticated User |
||||
==== |
||||
[source,java] |
||||
---- |
||||
SecurityContext context = SecurityContextHolder.getContext(); |
||||
Authentication authentication = context.getAuthentication(); |
||||
String username = authentication.getName(); |
||||
Object principal = authentication.getPrincipal(); |
||||
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); |
||||
---- |
||||
==== |
||||
|
||||
// FIXME: add links to HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal |
||||
|
||||
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. |
||||
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. |
||||
Spring Security's <<servlet-filterchainproxy,FilterChainProxy>> ensures that the `SecurityContext` is always cleared. |
||||
|
||||
Some applications aren't entirely suitable for using a `ThreadLocal`, because of the specific way they work with threads. |
||||
For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context. |
||||
`SecurityContextHolder` can be configured with a strategy on startup to specify how you would like the context to be stored. |
||||
For a standalone application you would use the `SecurityContextHolder.MODE_GLOBAL` strategy. |
||||
Other applications might want to have threads spawned by the secure thread also assume the same security identity. |
||||
This is achieved by using `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL`. |
||||
You can change the mode from the default `SecurityContextHolder.MODE_THREADLOCAL` in two ways. |
||||
The first is to set a system property, the second is to call a static method on `SecurityContextHolder`. |
||||
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. |
||||
Loading…
Reference in new issue