Spring Security 3.0.5 自定义过滤器问题
Posted
技术标签:
【中文标题】Spring Security 3.0.5 自定义过滤器问题【英文标题】:Spring Security 3.0.5 Custom Filter Issue 【发布时间】:2011-07-23 19:12:16 【问题描述】:当我尝试使用 spring security 3.0.5 配置新的自定义身份验证过滤器时,它会在服务器启动时调用自定义过滤器 (XMLAuthenticationFilter) 构造函数并抱怨没有指定 authenticationManager,请参见下面的异常。目标是使用基于表单和基于自定义的身份验证... XMLAuthenticationFilter.java 如何挂钩到 AuthenticationManager 以及是否应该在服务器启动时调用构造函数?
security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="dc" />
<global-method-security />
<http access-denied-page="/auth/denied.html">
<intercept-url filters="none" pattern="/javax.faces.resource/**" />
<intercept-url filters="none" pattern="/services/rest-api/1.0/**" />
<intercept-url filters="none" pattern="/preregistered/*"/>
<intercept-url
pattern="/**/*.xhtml"
access="ROLE_NONE_GETS_ACCESS" />
<intercept-url
pattern="/auth/**"
access="ROLE_ANONYMOUS,ROLE_USER" />
<intercept-url
pattern="/auth/*"
access="ROLE_ANONYMOUS" />
<intercept-url
pattern="/registered/*"
access="ROLE_USER" />
<intercept-url
pattern="/*"
access="ROLE_ANONYMOUS" />
<form-login
login-processing-url="/j_spring_security_check.html"
login-page="/auth/login.html"
default-target-url="/registered/home.html"
authentication-failure-url="/auth/login.html" />
<logout invalidate-session="true"
logout-success-url="/"
logout-url="/auth/logout.html"/>
<anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/>
<remember-me user-service-ref="userManager" key="ddddd"/>
<custom-filter after="FORM_LOGIN_FILTER" ref="xmlAuthenticationFilter"/>
</http>
<!-- Configure the authentication provider -->
<authentication-manager alias="am">
<authentication-provider user-service-ref="userManager">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
<authentication-provider ref="xmlAuthenticationProvider" />
</authentication-manager>
<bean id="xmlAuthenticationFilter" class="com.dc.api.service.impl.XMLAuthenticationFilter"/>
<bean id="xmlAuthenticationProvider" class="com.dc.api.service.impl.XMLAuthenticationProvider"/>
</beans:beans>
自定义 AuthenticationProvider:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
public class XMLAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
@Override
protected void additionalAuthenticationChecks(UserDetails arg0, UsernamePasswordAuthenticationToken arg1) throws AuthenticationException
// TODO Auto-generated method stub
@Override
protected UserDetails retrieveUser(String arg0, UsernamePasswordAuthenticationToken arg1) throws AuthenticationException
// TODO Auto-generated method stub
return null;
自定义过滤器(AbstractAuthenticationProcessingFilter):
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
public class XMLAuthenticationFilter extends AbstractAuthenticationProcessingFilter
public XMLAuthenticationFilter()
super("/xml_security_check");
@Override
public Authentication attemptAuthentication(HttpServletRequest arg0,
HttpServletResponse arg1) throws AuthenticationException,
IOException, ServletException
// TODO Auto-generated method stub
return null;
例外:
SEVERE: Exception sending context initialized event to listener instance of class org.jboss.resteasy.plugins.spring.SpringContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xmlAuthenticationFilter' defined in ServletContext resource [/WEB-INF/dc-context-api.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.jboss.resteasy.plugins.spring.SpringContextLoaderListener.contextInitialized(SpringContextLoaderListener.java:44)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4521)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5004)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:4999)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.IllegalArgumentException: authenticationManager must be specified
【问题讨论】:
【参考方案1】:您有一个别名为“am”的身份验证管理器,您在过滤器中的何处设置身份验证管理器属性?也许 XMLAuthenticationFilter 的 xml 配置应该是这样的:
<bean id="xmlAuthenticationFilter" class="com.dc.api.service.impl.XMLAuthenticationFilter">
<property name="authenticationManager" ref="am"/>
</bean>
我认为AbstractAuthenticationProcessingFilter 正在从其 afterPropertiesSet 方法中抛出异常(它应该在嵌套堆栈跟踪行之后可见 原因:java.lang.IllegalArgumentException:必须指定 authenticationManager )。 AbstractAuthenticationProcessingFilters 的文档说必须设置管理器:
认证过程
过滤器 要求您设置 authenticationManager 属性。一个 AuthenticationManager 需要 处理认证请求 通过实现创建的令牌 类。
【讨论】:
以上是关于Spring Security 3.0.5 自定义过滤器问题的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security入门(3-6)Spring Security 的鉴权 - 自定义权限前缀
使用 Spring Security 3.0.5 覆盖 ChannelProcessingFilter 不起作用
Spring Security 之自定义UserDetails