我有一个现有的Spring MVC应用程序,它当前没有使用SpringSecurity。我为Hibernate审计日志编写了一个AuditInterceptor,它需要一种方法来获取当前登录的用户。从我在网上找到的,最好的方法是通过SpringSecurity的SecurityContextHolder。但是,我现在并不需要任何其他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 :(得分:0)
我不确定你是怎么称它不是线程安全的。你的实现看起来很好。只要您每次都按照实现的方式检索上下文,它就是线程安全的。 SecurityContextHolder是ThreadLocalSecurityContextHolderStrategy的一个实例,它将SecurityContext存储在ThreadLocal中。
答案 1 :(得分:0)
从你的评论......
我有一个现有的Spring MVC应用程序,它当前没有使用SpringSecurity ...需要一种方法来获取当前登录的用户
你能不能只使用HttpServletRequest.getUserPrincipal()?
返回包含当前经过身份验证的用户名的java.security.Principal对象。如果用户尚未通过身份验证,则该方法返回null。
最后,您对线程安全的评论似乎很可疑,因为安全上下文对象和主目标对象是不可变的,默认情况下存储在ThreadLocal存储中,这使得它们完全是线程安全的。
答案 2 :(得分: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确保在需要时适当地清除所有内容。