将自定义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(); }
- Struts 2 – 在身份validation拦截器之后重定向到正确的操作
- Java – javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份validation
- 如何使用DaoAuthenticationProvider以编程方式使用Spring Security对用户进行身份validation
- 如何在SNMP4J中使用非对称密钥或证书身份validation?
- 在Jetty服务器中,如何获取需要客户端身份validation时使用的客户端证书?
- RestTemplate与pem证书
- 即使在SpringMVC中包含密钥库证书后,也无法对服务器进行身份validation
- Spring Security,表单登录和并发会话
- Java SSO:针对Active Directory的Kerberos身份validation