I have multiple projects that need to pass user login information to common-api project that they call. The common-api does not have user credentials passed in via method calls, so I am hoping to make this information available via Threadlocal variables.
The first such project that needs to make this information available is a rest-web-service-api project that uses Spring Security, and sits on top of my common-api project.
I see that Spring Security stores the user information in a ThreadLocal variable... is there a way to access this from the common-api project without necessarily needing to know that Spring Security is who set it? I am quite unfamiliar with Spring Security and new to using Threadlocals so any help would be greatly appreciated.
Posting my own solution here in case it's useful down the road to someone else.
Spring security (by default) does in fact store the user information in a Threadlocal variable, but the common-api will not have access to it unless it adds a spring-security dependency -if it does, the user information can be accessed (assuming you're executing in the same thread) using the following snippet:
SecurityContext secureContext = SecurityContextHolder.getContext();
Authentication auth = secureContext.getAuthentication();
Object principal = auth.getPrincipal();
String userName = null;
if (principal instanceof UserDetails) {
UserDetails userDetails = (UserDetails) principal;
userName = userDetails.getUsername();
} else {
userName = principal.toString();
}
The solution I implemented was different however, because I did not want to introduce Spring Security to the common-api project, and I couldn't always rely on Spring Security being in the user of the API. So, I created a Singleton bean in the common-api that contains my own defined ThreadLocal variables that can be set from other projects and accessed from the common-api project (again, assuming they're running in the same thread).
Code Snippet:
public class CommonAPIThreadLocalStorageManager {
private static CommonAPIThreadLocalStorageManager instance;
// Typical singleton private constructor, static getInstance here
private ThreadLocal<String> userID = new ThreadLocal<String>();
public String getUserID() {
return userID.get();
}
public void setUserID(String userID) {
this.userID.set(userID);
}