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

Spring Boot + Spring Security自定义用户认证

Gateway 整合 Spring Security鉴权

Spring Security-用户密码自定义加密