如何在Spring自定义Authentication Provider中获取配置Bean?
你遇到的问题根源在于:FacesContext仅在JSF请求处理的线程中存在,而Spring Security的认证流程(比如通过过滤器处理的登录请求)并不一定处于JSF上下文环境中,所以调用FacesContext.getCurrentInstance()会返回null,进而导致获取WebApplicationContext失败。
下面是两种可行的解决方案,优先推荐第一种依赖注入的方式:
方案一:使用Spring依赖注入(最优解)
既然你的MySettingsBean是Spring容器管理的Bean,直接通过依赖注入的方式注入到自定义的LdapAuthenticationProvider中,完全不需要手动获取上下文。
1. 修改自定义AuthenticationProvider类
添加MySettingsBean的私有属性,并提供setter方法(或使用@Autowired注解):
public class CustomLdapAuthenticationProvider extends LdapAuthenticationProvider { private MySettingsBean mySettings; // 提供setter供Spring注入 public void setMySettings(MySettingsBean mySettings) { this.mySettings = mySettings; } @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { // 直接使用注入的mySettings对象 String configValue = mySettings.getYourConfigProperty(); // 后续认证逻辑处理 } }
如果你的项目启用了Spring注解驱动,也可以直接用@Autowired简化:
public class CustomLdapAuthenticationProvider extends LdapAuthenticationProvider { @Autowired private MySettingsBean mySettings; @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { // 使用mySettings } }
2. 在applicationContext.xml中配置注入
确保自定义的AuthenticationProvider Bean配置时,注入mySettings:
<!-- 你的mySettings Bean配置 --> <bean id="mySettings" class="au.org.myOrganisation.MySettingsBean"> <property name="location" value="classpath:mySettings.properties"/> </bean> <!-- 自定义认证Provider,注入mySettings --> <bean id="customLdapAuthProvider" class="com.yourpackage.CustomLdapAuthenticationProvider"> <!-- 其他必要配置,比如userDetailsContextMapper、ldapAuthenticator等 --> <property name="mySettings" ref="mySettings"/> </bean>
这种方式完全符合Spring的设计理念,避免了上下文获取的耦合,也不会出现空指针问题。
方案二:直接获取Spring根上下文(备选)
如果因为某些原因无法使用依赖注入,可以通过Spring的ContextLoader获取全局WebApplicationContext,不需要依赖FacesContext:
@Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); if (ctx != null) { MySettingsBean mySettings = ctx.getBean(MySettingsBean.class); // 使用mySettings } else { // 处理上下文为空的异常情况 throw new IllegalStateException("Spring WebApplicationContext not found"); } }
注意:这种方式需要确保你的项目已经配置了ContextLoaderListener(通常在web.xml中配置),否则getCurrentWebApplicationContext()会返回null。
内容的提问来源于stack exchange,提问作者David Buddrige

