2011-03-25 76 views
1

我有一個現在沒有使用SpringSecurity的Spring MVC應用程序。我爲Hibernate審計日誌寫了一個AuditInterceptor,它需要一種獲取當前登錄用戶的方法。從我在網上可以找到的,最好的方法是通過SpringSecurity的SecurityContextHolder。不過,我現在並不需要其他SpringSecurity功能,我不想重寫當前應用程序如何進行身份驗證或授權。檢索用戶所需的最小SpringSecurity配置

基本上,我所需要的是將登錄用戶存儲到SecurityContextHolder中所需的最小配置數量,並在我的AuditInterceptor中再次取回它。


我第一次嘗試是以下行添加到當前存在的登錄頁面:

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

,並添加以下的攔截器:

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

這是成功的,但不幸的是不是線程安全的。任何人有任何其他想法?

回答

0

我不知道你是怎麼稱呼它不是線程安全的。你的實現看起來非常好。只要您按照您實施的方式檢索上下文,它就是線程安全的。 SecurityContextHolder是ThreadLocalSecurityContextHolderStrategy的一個實例,它將SecurityContext存儲在一個ThreadLocal中。

0

從您的評論...

我已在當前​​登錄的用戶不目前使用SpringSecurity這就需要一種方式來獲得現有的Spring MVC應用程序...

燦你不只是使用HttpServletRequest.getUserPrincipal()

返回一個java.security.Principal對象,其中包含當前已通過身份驗證的用戶的名稱。如果用戶尚未通過身份驗證,則該方法返回null。

最後,您對線程安全性的評論看起來很可疑,因爲安全上下文對象和pricipal對象是不可變的,並且默認存儲在ThreadLocal存儲中,這使得它們完全線程安全。

0

感謝您的幫助,所有。我能夠從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. 

再往挖掘發現我的問題的心臟 - 我錯過了一個關鍵的bean定義:

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

的SecurityContextPersistenceFilter確保一切在需要時得到適當清除。