开发者

Minimum SpringSecurity configuration needed to retrieve user

开发者 https://www.devze.com 2023-02-20 04:37 出处:网络
I have an existing Spring MVC application which does not currently use SpringSecurity. I wrote an AuditInterceptor for Hibernate audit logs, which needs a way to get the currently logged in user. From

I have an existing Spring MVC application which does not currently use SpringSecurity. I wrote an AuditInterceptor for Hibernate audit logs, which needs a way to get the currently logged in user. From what I can find online, the best way to do that is via SpringSecurity's SecurityContextHolder. However, I don't really need any of the other SpringSecurity features at this time, and I don't want to have to rewrite how the application does authentication or authorization currently.

Basically, what I am looking for is the minimum amount of configuration necessary in order to store the logged in user into the SecurityContextHolder, and get it back out again inside of my AuditInterceptor.

My first attempt was to add the following line to the Login page tha开发者_如何学Pythont currently exists:

Authentication auth = new UsernamePasswordAuthenticationToken(u.getName(), u.getPassword());
SecurityContextHolder.getContext().setAuthentication(auth);

And to add the following to the interceptor:

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();
}

This was successful, but unfortunately not thread safe. Anybody have any other ideas?


I'm not sure how you are calling it not thread safe. Your implementation looks perfectly fine. It is thread safe as long as you retrieve the context each time just the way you have implemented. SecurityContextHolder is an instance of ThreadLocalSecurityContextHolderStrategy which stores SecurityContext in a ThreadLocal.


From your comment...

I have an existing Spring MVC application which does not currently use SpringSecurity ... which needs a way to get the currently logged in user

Can you not just use HttpServletRequest.getUserPrincipal()?

Returns a java.security.Principal object containing the name of the current authenticated user. If the user has not been authenticated, the method returns null.

Finally, your comments on thread safety seem dubious since security context objects and pricipal objects are immutable and are stored in ThreadLocal storage by default which makes them perfectly thread safe.


Thanks for the help, all. I was able to find the following explanation from http://static.springsource.org/spring-security/site/docs/3.0.x/reference/technical-overview.html:

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().setAuthentication(anAuthentication), then 
the Authentication object will change in all concurrent threads which share the 
same SecurityContext instance.

A little further digging revealed the heart of my problem - I was missing a critical bean definition:

<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>

The SecurityContextPersistenceFilter makes sure that everything gets cleared out appropriately when needed.

0

精彩评论

暂无评论...
验证码 换一张
取 消