检索用户所需的最低 SpringSecurity 配置

问题描述 投票:0回答:4

我有一个现有的 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();
}

这是成功的,但不幸的是不是线程安全的。大家还有其他想法吗?

java spring spring-security
4个回答
0
投票

我不确定你如何称其为非线程安全。您的实现看起来非常好。只要您每次按照您实现的方式检索上下文,它就是线程安全的。 SecurityContextHolder 是 ThreadLocalSecurityContextHolderStrategy 的一个实例,它将 SecurityContext 存储在 ThreadLocal 中。


0
投票

根据您的评论...

我有一个现有的 Spring MVC 应用程序,当前不使用 SpringSecurity ...它需要一种方法来获取当前登录的用户

你能不能只使用HttpServletRequest.getUserPrincipal()

返回一个 java.security.Principal 对象,其中包含当前经过身份验证的用户的名称。如果用户尚未通过身份验证,该方法返回 null。

最后,您对线程安全的评论似乎很可疑,因为安全上下文对象和主要对象是不可变的,并且默认情况下存储在 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 确保在需要时正确清除所有内容。


0
投票

阅读此内容: https://docs.spring.io/spring-security/reference/servlet/authentication/session-management.html#store-authentication-manually

你需要使用 securityContextHolderStrategy 而不是静态访问 SecurityContextHolder

© www.soinside.com 2019 - 2024. All rights reserved.