使用自定义AuthenticationProcessingFilter以&lt;形式登录&GT; (自动配置= QUOT;真&QUOT;) [英] Using Custom AuthenticationProcessingFilter with <form-login> (auto-config="true")
问题描述
春季安全(2.0.x版本)HTTP命名空间,形式,登录定义自动使用AuthenticationProcessingFilter。
&LT;形式登录的login-page =/ logon.jsp
默认目标URL ='/针对home.jsp
始终使用默认目标=真/&GT;
我也知道,如果我设置自动配置=FALSE
我可以通过提供定制的bean定义自定义验证。
我有一个扩展AuthenticationProcessingFilter CustomAuthenticationProcessingFilter覆盖obtainUsername,并使用自定义逻辑来获得用户名一个比过去。
保护字符串obtainUsername(HttpServletRequest的请求){
//自定义的逻辑,从参数/饼干/头等等返回用户名...
}
时有可能使用CustomAuthenticationProcessingFilter同时仍然使用自动配置=真正的&LT;形式登录&GT;
无需定义customAuthFilter和所有相关的豆类?
&LT;豆类:豆类ID =customAuthFilter级=x.y.z.CustomAuthenticationProcessingFilter&GT;
&LT;定制过滤器位置=AUTHENTICATION_PROCESSING_FILTER/&GT;
&LT;豆类:属性名=defaultTargetUrlVALUE =/针对home.jsp&GT;&LT; /豆:性&gt;
...
...
&LT; /豆:豆&GT;
事实上,春天的命名空间处理器内部定义一个名为豆 _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)豆;
WebAuthenticationDetailsSource源=(WebAuthenticationDetailsSource)filter.getAuthenticationDetailsSource();
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 doFilter
method. ( 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) && 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屋!