自定义Spring 3.0安全过滤器、多个入口点、AuthenticationProvider

自定义Spring 3.0安全过滤器、多个入口点、AuthenticationProvider,spring,authentication,spring-security,Spring,Authentication,Spring Security,我需要我的安全具有以下逻辑: 检查是否存在标头参数 根据参数是否存在,执行重定向到登录页面(如果未经过身份验证)或检查基本身份验证令牌 在这两种情况下,我有相同的身份验证提供程序,但我不能让它工作。 委派入口点工作正常,但我从未进入我的自定义authenticationprovider 这是我的安全配置: <security:global-method-security secured-annotations="enabled" /> <security:ht

我需要我的安全具有以下逻辑:

  • 检查是否存在标头参数
  • 根据参数是否存在,执行重定向到登录页面(如果未经过身份验证)或检查基本身份验证令牌
  • 在这两种情况下,我有相同的身份验证提供程序,但我不能让它工作。 委派入口点工作正常,但我从未进入我的自定义authenticationprovider

    这是我的安全配置:

        <security:global-method-security
        secured-annotations="enabled" />
    
    <security:http entry-point-ref="delegatingAuthenticationEntryPoint"
        use-expressions="true" auto-config="false">
        <!-- <security:custom-filter position="FORM_LOGIN_FILTER" -->
        <!-- ref="usernamePasswordAuthenticationFilter" /> -->
        <!-- <security:custom-filter position="BASIC_AUTH_FILTER" -->
        <!-- ref="basicAuthenticationFilter" /> -->
        <security:intercept-url pattern="/login*"
            filters="none" />
        <security:intercept-url pattern="/portimaLogin*"
            filters="none" />
        <security:intercept-url pattern="/**"
            access="isAuthenticated()" />
    </security:http>
    
    <bean id="delegatingAuthenticationEntryPoint"
        class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
        <constructor-arg>
            <map>
                <entry key="hasHeader('portima','true')" value-ref="PortimaLoginUrlAuthenticationEntryPoint" />
            </map>
        </constructor-arg>
        <property name="defaultEntryPoint" ref="authenticationEntryPoint" />
    </bean>
    
    <bean id="usernamePasswordAuthenticationFilter"
        class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
    </bean>
    
    <bean id="basicAuthenticationFilter"
        class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
    </bean>
    
    <bean id="PortimaLoginUrlAuthenticationEntryPoint"
        class="be.ap.common.security.spring.PortimaLoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="${portima.login.page}" />
    </bean>
    
    <bean id="authenticationEntryPoint"
        class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
        <property name="realmName" value="AP" />
    </bean>
    
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider
            ref="authenticationProvider" />
    </security:authentication-manager>
    
    <bean id="authenticationProvider" class="be.ap.common.security.spring.APAuthenticationProvider" />
    
    <bean id="userDetailsService" class="be.ap.common.security.spring.APUserDetailsService" />
    
    
    

    有什么想法吗?

    我终于有办法了

    这是我的上下文文件:

        <security:http entry-point-ref="delegatingAuthenticationEntryPoint"
        use-expressions="true">
        <security:custom-filter position="PRE_AUTH_FILTER"
            ref="preAuthenticationFilter" />
        <security:custom-filter position="FORM_LOGIN_FILTER"
            ref="usernamePasswordAuthenticationFilter" />
        <security:custom-filter position="BASIC_AUTH_FILTER"
            ref="basicAuthenticationFilter" />
        <security:intercept-url pattern="/login*"
            filters="none" />
        <security:intercept-url pattern="/portimaLogin*"
            filters="none" />
        <security:intercept-url pattern="/accessDenied*"
            filters="none" />
        <security:intercept-url pattern="/**"
            access="isAuthenticated()" />
        <security:access-denied-handler ref="accessDeniedHandler" />
    </security:http>
    
    <!-- Spring Security Custom Filters -->
    
    <bean id="usernamePasswordAuthenticationFilter"
        class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
    </bean>
    
    <bean id="basicAuthenticationFilter"
        class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
    </bean>
    
    <bean id="preAuthenticationFilter" class="be.ap.common.security.spring.APPreAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>
    
    <!-- Spring Security Custom EntryPoint -->
    
    <bean id="delegatingAuthenticationEntryPoint"
        class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
        <constructor-arg>
            <map>
                <entry key="hasHeader('portima','true')" value-ref="PortimaLoginUrlAuthenticationEntryPoint" />
            </map>
        </constructor-arg>
        <property name="defaultEntryPoint" ref="authenticationEntryPoint" />
    </bean>
    
    <bean id="PortimaLoginUrlAuthenticationEntryPoint"
        class="be.ap.common.security.spring.PortimaLoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="${portima.login.page}" />
    </bean>
    
    <bean id="authenticationEntryPoint"
        class="be.ap.common.security.spring.APBasicAuthenticationEntryPoint">
        <property name="realmName" value="AP" />
    </bean>
    <bean id="accessDeniedHandler"
        class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
        <property name="errorPage" value="/accessDenied" />
    </bean>
    
    <bean id="authenticationFailureHandler"
        class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
        <property name="exceptionMappings">
            <props>
                <prop
                    key="org.springframework.security.authentication.BadCredentialsException">
                    /accessDenied
                </prop>
                <prop
                    key="org.springframework.security.authentication.CredentialsExpiredException">
                    /accessDenied
                </prop>
                <prop key="org.springframework.security.authentication.LockedException">
                    /accessDenied
                </prop>
                <prop
                    key="org.springframework.security.authentication.DisabledException">
                    /accessDenied
                </prop>
            </props>
        </property>
    </bean>
    
    <!-- Spring Security Authentication Manager -->
    
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider
            ref="authenticationProvider" />
    </security:authentication-manager>
    
    <bean id="authenticationProvider" class="be.ap.common.security.spring.APAuthenticationProvider" />
    
    <bean id="userDetailsService" class="be.ap.common.security.spring.APUserDetailsService" />
    
    <!-- for Mock -->
    <bean id="SSOService" class="be.ap.security.service.SSOServiceMockImpl" />
    
    
    /拒绝访问
    /拒绝访问
    /拒绝访问
    /拒绝访问
    
    正如你所看到的,我也添加了一些东西

    为了修复它,我移除了auto-config属性,取消了过滤器的注释,并正确地定义了它们

    对于其他想要快速了解其功能的人,以下是流程:

  • PRE_AUTH_筛选器将检查类似SSO的服务,以预先填充身份验证对象(如果已在SSO中进行身份验证)
  • delegatingAuthenticationEntryPoint然后将根据请求标头选择如何进行身份验证
  • 这两种方式是:
    • 自定义LoginUrlAuthenticationEntryPoint
    • 自定义基本身份验证入口点
  • 当预授权使用我的SSO服务时,BasicAuth和LoginURLAuth使用相同的AuthenticationProvider


    希望它能帮助别人

    您的自定义AuthenticationProvider是否正确实现了
    supports()
    方法?如果它为
    UsernamePasswordAuthenticationToken
    类返回false,则它将永远不会被要求处理由筛选器创建的身份验证令牌。它甚至不会进入support方法…@Override public boolean supports(ClassIt似乎实际上忽略了声明的筛选器。请参阅手册()查看如何替换命名空间配置创建的筛选器。