I use spring security in my project.
I have feature to change login. To achieve this aim I use following code
Authentication authentication = ... SecurityContextHolder.getContext().setAuthentication(authentication);
But now I am resesarching this code in details and see that authentication field is not volatile
thus visibility is not guaranteed:
public class SecurityContextImpl implements SecurityContext { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; // ~ Instance fields // ================================================================================================ private Authentication authentication;
Should I wrap my code with my own synchronization to achieve visibility?
I have read https://stackoverflow.com/a/30781541/2674303
In an application which receives concurrent requests in a single session, the same SecurityContext instance will be shared between threads. Even though a ThreadLocal is being used, it is the same instance that is retrieved from the HttpSession for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just use SecurityContextHolder.getContext(), and call setAuthentication(anAuthentication) on the returned context object, then the Authentication object will change in all concurrent threads which share the same SecurityContext instance. You can customize the behaviour of SecurityContextPersistenceFilter to create a completely new SecurityContext for each request, preventing changes in one thread from affecting another. Alternatively you can create a new instance just at the point where you temporarily change the context. The method SecurityContextHolder.createEmptyContext() always returns a new context instance.
but I don't understand how spring does guaranties visibility. There are just written that each thread within session will see changes. but there is no answer how fast? and more important - visibility mechanism is not explained
A security context defines privilege and access control settings for a Pod or Container. Security context settings include, but are not limited to: Discretionary Access Control: Permission to access an object, like a file, is based on user ID (UID) and group ID (GID).
The fsGroup setting defines a group which Kubernetes will change the permissions of all files in volumes to when volumes are mounted by a pod. The behavior here is also controlled by the fsGroupChangePolicy , which can be set to onRootMismatch or Always .
The Kubernetes Pod SecurityContext provides two options runAsNonRoot and runAsUser to enforce non root users. You can use both options separate from each other because they test for different configurations. When you set runAsNonRoot: true you require that the container will run with a user with any UID other than 0.
Running a pod in a privileged mode means that the pod can access the host's resources and kernel capabilities. You can turn a pod into a privileged one by setting the privileged flag to `true` (by default a container is not allowed to access any devices on the host).
Your doubts are justified, visibility is not guaranteed. ThreadLocal isn't thread-safe, when all ThreadLocalMap's entries store the same object.
Referenced documentation part, Storing the SecurityContext between requests, warns you about that fact and proposes possible solutions to change the context in a way, that prevents affect on other threads.
An example of such solution is the RunAs mechanism, which changes the context during the secure object callback phase.
But, as I understand your question, you need to change the user's login (i.e. username) "on the fly". If I'm right, then the problem is, when you'd set a modified Authentication
- another thread could read the old value. To avoid this race condition you need to make a login write happens-before every sequential login read.
Authentication
interface has the getPrincipal()
method, which returns an Object
, which is an UserDetails
instance (in most cases). This object is usually used to obtain a username for the current (authenticated) user.
So, if you want to change the login for authenticated user "on the fly", you can modify the username
property in this UserDetails
object.
Possible way to make it in a thread-safe manner is a custom UserDetails
implementation with the volatile String username
property (default User
implementation has an immutable username).
You should also create and wire into your configuration an UserDetailsService
implementation, which will use your custom UserDetails
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With