将自定义AuthenticationProcessingFilter与一起使用(auto-config =“true”)

Spring security(2.0.x)http命名空间,表单登录定义自动使用AuthenticationProcessingFilter。

 

我也知道如果我设置auto-config="false"我可以通过提供自定义bean定义来自定义身份validation。

我有CustomAuthenticationProcessingFilter扩展AuthenticationProcessingFilter覆盖acquireUsername并使用自定义逻辑来获取用户名而不是传递的用户名。

 protected String obtainUsername(HttpServletRequest request) { // custom logic to return username from parameter/cookies/header etc ... } 

是否可以使用CustomAuthenticationProcessingFilter,同时仍然使用auto-config="true" 而无需定义customAuthFilter和所有依赖bean?

     ... ...  

介绍

Spring Security 2.0处于维护模式,因此不会有任何官方更新。 但是,您可以使用一些方法来解决此问题。

的BeanPostProcessor

您可以从Spring Security FAQ中使用的技巧是使用BeanPostProcessor。 您可以返回自定义filter,而不是修改属性。 一个例子可能是这样的:

 public class CustomFilterBeanPostProcessor implements BeanPostProcessor { private Filter customFilter; public Object postProcessAfterInitialization(Object bean, String name) { if (bean instanceof AuthenticationProcessingFilter) { return customFilter; } return bean; } public Object postProcessBeforeInitialization(Object bean, String name) { return bean; } public void setFilter(Filter filter) { this.customFilter = filter; } } 

然后您的配置将包括以下内容:

     

在属性之前使用

另一种方法是在AuthenticationProcessingFilter之前插入自定义Filter。 这将有一个额外的filter,但它应该是微创的,因为它很小并且不应该到达(即,因为自定义filter仅在AuthenticationProcessingFilter忽略请求时继续FilterChain)。 使用此方法的示例配置如下所示:

    ... ...  

唉,因为看起来(如果我没错),由于AuthenticationProcessingFilter类名在< HttpSecurityBeanDefinitionParser >中被硬编码,所以无法做多少:(

 if (formLoginElt != null || autoConfig) { FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check", "org.springframework.security.ui.webapp.AuthenticationProcessingFilter"); 

如果filter类是一个配置属性并且在外部进行控制(就像default-target-url )可能会使用属性authentication-filter-class器类,那会更好

  

希望spring的人们正在倾听;)

事实上,spring的命名空间处理程序在内部为AuthenticationProcessingFilter定义了名为_formLoginFilter bean(参见BeanIds完整列表)。 有一些方法可以解决这个问题(即使用来自DaoAuthenticationProvider的j_username之外的其他东西进行身份validation,比如说从头部获取用户名等…)

使用Spring AOP bean()语法拦截doFilter()

定义一个切入点,查找名称为_formLoginFilter bean并拦截doFilter方法。 ( AuthenticationProcessingFilter.doFilter() method )并有条件地委托给其他人

 public class AuthenticationProcessingFilterAspect { private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationProcessingFilterAspect.class); public Object intercept(ProceedingJoinPoint pjp) throws Throwable { LOGGER.info("intercept------------------{}",pjp.toLongString()); //Delegate to customised method instead of default pjp.proceed() return pjp.proceed(); } } 

配置

       

使用CustomWebAuthenticationDetails进行身份validation

为AuthenticationProcessingFilter bean定义一个bean后处理器,它注入了填充自定义字段的CustomWebAuthenticationDetails

 public class AuthenticationProcessingFilterBeanPostProcessor implements BeanPostProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationProcessingFilterBeanPostProcessor.class); public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("_formLoginFilter".equals(beanName) && bean instanceof AuthenticationProcessingFilter) { AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) bean; WebAuthenticationDetailsSource source = (WebAuthenticationDetailsSource) filter.getAuthenticationDetailsSource(); source.setClazz(CustomWebAuthenticationDetails.class); } return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @SuppressWarnings("serial") public static class CustomWebAuthenticationDetails extends WebAuthenticationDetails { private String customAttribute;//customfield public CustomWebAuthenticationDetails(HttpServletRequest request) { super(request); //Build custom attributes that could be used elsewhere (say in DaoAuthenticationProvider ) //with (CustomWebAuthenticationDetails)authentication.getDetails() customAttribute = request.getHeader("username"); } public boolean getCustomAttribute() { return customAttribute; } } } 

配置

  

使用线程绑定请求进行实际身份validation(在DaoAuthenticationProvider中)

使用getHttpServletRequest()访问threadbound请求对象,并使用request.getHeader(“username”)进行自定义身份validation。

 public static HttpServletRequest getHttpServletRequest(){ return((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); } 

如果请求不是通过DispatcherServlet,还需要在web.xml中定义它

  requestContextFilter org.springframework.web.filter.RequestContextFilter   requestContextFilter /j_spring_security_check FORWARD REQUEST   requestContextFilter /j_spring_security_logout FORWARD REQUEST  

如果它的faces应用程序使用FacesContext.getCurrentInstance()

 public static HttpServletRequest getHttpServletRequest(){ FacesContext context = FacesContext.getCurrentInstance(); return (HttpServletRequest) context.getExternalContext().getRequest(); }