使用自定义AuthenticationProcessingFilter以<形式登录> (自动配置= QUOT;真") [英] Using Custom AuthenticationProcessingFilter with <form-login> (auto-config="true")

查看:851
本文介绍了使用自定义AuthenticationProcessingFilter以<形式登录> (自动配置= QUOT;真")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

春季安全(2.0.x版本)HTTP命名空间,形式,登录定义自动使用AuthenticationProcessingFilter。

 <形式登录的login-page =/ logon.jsp
默认目标URL ='/针对home.jsp
始终使用默认目标=真/>

我也知道,如果我设置自动配置=FALSE我可以通过提供定制的bean定义自定义验证。

我有一个扩展AuthenticationProcessingFilter CustomAuthenticationProcessingFilter覆盖obtainUsername,并使用自定义逻辑来获得用户名一个比过去。

 保护字符串obtainUsername(HttpServletRequest的请求){
   //自定义的逻辑,从参数/饼干/头等等返回用户名...
}

时有可能使用CustomAuthenticationProcessingFilter同时仍然使用自动配置=真正的<形式登录> 无需定义customAuthFilter和所有相关的豆类?

 <豆类:豆类ID =customAuthFilter级=x.y.z.CustomAuthenticationProcessingFilter>
    <定制过滤器位置=AUTHENTICATION_PROCESSING_FILTER/>
    <豆类:属性名=defaultTargetUrlVALUE =/针对home.jsp>< /豆:性>
    ...
    ...
  < /豆:豆>


解决方案

事实上,春天的命名空间处理器内部定义一个名为豆 _formLoginFilter 为AuthenticationProcessingFilter(请参阅<一个href=\"http://static.springsource.org/spring-security/site/xref/org/springframework/security/config/BeanIds.html\"相对=nofollow> BeanIds 的完整列表)。有很多方法这个问题要解决coulpe(即使用比DaoAuthenticationProvider的时候为j_username其他东西进行身份验证,喜欢说采取用户名头,从等)

使用Spring AOP的豆()语法拦截的doFilter()

定义一个切入点,看起来与名称 _formLoginFilter 和截距的doFilter 法豆。 ( AuthenticationProcessingFilter.doFilter()方法),并有条件地委托给别的东西。

 公共类AuthenticationProcessingFilterAspect {
  私有静态最后记录器记录仪= LoggerFactory.getLogger(AuthenticationProcessingFilterAspect.class);
  公共拦截对象(ProceedingJoinPoint PJP)抛出的Throwable
    LOGGER.info(截距------------------ {},pjp.toLongString());
    //委托定制化方法,而不是默认pjp.proceed()
    返回pjp.proceed();
  }
}

配置

 &LT;豆类:豆类ID =authFilterAspect级=x.y.z.AuthenticationProcessingFilterAspect/&GT;
&LT; AOP:配置&GT;
  &LT; AOP:一方面REF =authFilterAspect&GT;
    &LT; AOP:约切入点=豆(_formLoginFilter)放大器;放大器;&放大器;放大器;执行(*的doFilter(..))方法=拦截/&GT;
  &LT; / AOP:一方面&GT;
&LT; / AOP:配置&GT;

使用CustomWebAuthenticationDetails做认证

定义AuthenticationProcessingFilter bean中注入CustomWebAuthenticationDetails其中填充自定义字段一个bean后处理器

 公共类AuthenticationProcessingFilterBeanPostProcessor工具
    {的BeanPostProcessor  私有静态最后记录器记录仪= LoggerFactory.getLogger(AuthenticationProcessingFilterBeanPostProcessor.class);  公共对象postProcessAfterInitialization(对象豆,字符串beanName)
      抛出BeansException {
    如果(_formLoginFilter.equals(beanName)及&放大器;豆的instanceof AuthenticationProcessingFilter){
      AuthenticationProcessingFilter过滤=(AuthenticationProcessingFilter)豆;
      WebAuthenticationDetailsS​​ource源=(WebAuthenticationDetailsS​​ource)filter.getAuthenticationDetailsS​​ource();
      source.setClazz(CustomWebAuthenticationDetails.class);
    }
    返回豆;
  }  公共对象postProcessBeforeInitialization(对象豆,字符串beanName)
      抛出BeansException {
    返回豆;
  }  @燮pressWarnings(串行)
  公共静态类CustomWebAuthenticationDetails扩展
      WebAuthenticationDetails {
    私人字符串customAttribute; //的CustomField
    公共CustomWebAuthenticationDetails(HttpServletRequest的请求){
      超(请求);
      //构建一个能够在其他地方使用的自定义属性(在DaoAuthenticationProvider的时候说的)
      //使用(CustomWebAuthenticationDetails)authentication.getDetails()
      customAttribute = request.getHeader(用户名);
    }
    公共布尔getCustomAttribute(){
      返回customAttribute;
    }
  }
}

配置

 &LT;豆类:豆类ID =authFilterProcessor级=x.y.z.AuthenticationProcessingFilterBeanPostProcessor/&GT;

使用线程必然要求做实际的认证(内需要把DaoAuthenticationProvider)

使用getHttpServletRequest()来访问threadbound请求对象,并使用request.getHeader(用户名)做自定义验证。

 公共静态HttpServletRequest的getHttpServletRequest(){
  。收益率((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())调用getRequest();
}

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

 &LT;滤光器&gt;
  &LT;过滤器名称&gt;&RequestContextFilter两个LT; /过滤器名称&gt;
  &LT;过滤器类和GT; org.springframework.web.filter.RequestContextFilter&LT; /过滤器类&GT;
&LT; /滤光器&gt;
&LT;过滤器映射&GT;
  &LT;过滤器名称&gt;&RequestContextFilter两个LT; /过滤器名称&gt;
  &LT; URL模式&GT; / j_spring_security_check&LT; / URL模式&GT;
  &LT;分派器GT;前向LT; /分派器GT;
  &LT;分派器GT;请求&LT; /分派器GT;
&LT; /过滤器映射&GT;
&LT;过滤器映射&GT;
  &LT;过滤器名称&gt;&RequestContextFilter两个LT; /过滤器名称&gt;
  &LT; URL模式&GT; / j_spring_security_logout&LT; / URL模式&GT;
  &LT;分派器GT;前向LT; /分派器GT;
  &LT;分派器GT;请求&LT; /分派器GT;
&LT; /过滤器映射&GT;

如果它的面孔应用程序中使用 FacesContext.getCurrentInstance()

 公共静态HttpServletRequest的getHttpServletRequest(){
    FacesContext的上下文= FacesContext.getCurrentInstance();
    回报(HttpServletRequest的)context.getExternalContext()调用getRequest()。
}

Spring security (2.0.x) http namespace, form-login definition automatically uses AuthenticationProcessingFilter.

<form-login login-page='/logon.jsp' 
default-target-url='/home.jsp' 
always-use-default-target='true' />

I also know that If I set auto-config="false" I can customise authentication by providing custom bean definition.

I have CustomAuthenticationProcessingFilter that extends AuthenticationProcessingFilter overrides obtainUsername and uses custom logic to get username than the one passed.

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

Is it possible to use CustomAuthenticationProcessingFilter while still using auto-config="true" <form-login> without needing to define customAuthFilter and all dependent beans ?

  <beans:bean id="customAuthFilter" class="x.y.z.CustomAuthenticationProcessingFilter">
    <custom-filter  position="AUTHENTICATION_PROCESSING_FILTER" />
    <beans:property name="defaultTargetUrl" value="/home.jsp"></beans:property>
    ...
    ...
  </beans:bean>

解决方案

The fact is that spring's namespace handler internally defines bean with the name _formLoginFilter for AuthenticationProcessingFilter (See for BeanIds complete list). There are coulpe of ways to workaround with this issue (i.e to authenticate using something other than j_username from DaoAuthenticationProvider , like say take username from header etc... )

Use Spring AOP bean() syntax to intercept doFilter()

Define a pointcut that looks for bean with name _formLoginFilter and intercepts doFiltermethod. ( AuthenticationProcessingFilter.doFilter() method) and conditionally delegate to something else

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();
  }
}

Config

<beans:bean id="authFilterAspect" class="x.y.z.AuthenticationProcessingFilterAspect" />
<aop:config>
  <aop:aspect ref="authFilterAspect">
    <aop:around pointcut="bean(_formLoginFilter) &amp;&amp; execution(* doFilter(..))" method="intercept"/>
  </aop:aspect>
</aop:config>

Use CustomWebAuthenticationDetails to do authentication

Define a bean postprocessor for AuthenticationProcessingFilter bean that injects CustomWebAuthenticationDetails which populates custom fields

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;
    }
  }
}

Config

<beans:bean id="authFilterProcessor" class="x.y.z.AuthenticationProcessingFilterBeanPostProcessor" />

Use thread bound request to do actual authentication (within DaoAuthenticationProvider)

Use getHttpServletRequest() to access threadbound request object and use request.getHeader("username") to do custom authentication.

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

Also need to Define this in web.xml if request is not through DispatcherServlet

<filter>
  <filter-name>requestContextFilter</filter-name>
  <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>requestContextFilter</filter-name>
  <url-pattern>/j_spring_security_check</url-pattern>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
  <filter-name>requestContextFilter</filter-name>
  <url-pattern>/j_spring_security_logout</url-pattern>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>

If its faces application use FacesContext.getCurrentInstance()

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

这篇关于使用自定义AuthenticationProcessingFilter以&lt;形式登录&GT; (自动配置= QUOT;真&QUOT;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆