【问题标题】:Custom Spring 3.0 Security Filters, Multiple EntryPoints, AuthenticationProvider自定义 Spring 3.0 安全过滤器、多个入口点、AuthenticationProvider
【发布时间】:2013-01-27 14:21:55
【问题描述】:

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

  1. 检查是否存在标头参数
  2. 根据参数是否存在重定向到登录页面(如果未通过身份验证),或检查基本身份验证令牌

在这两种情况下,我都有相同的身份验证提供程序,但我无法让它工作。 委托入口点工作正常,但我从来没有进入我的自定义身份验证提供程序......

这是我的安全配置:

    <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" />

有什么想法吗?

【问题讨论】:

  • 您的自定义 AuthenticationProvider 是否正确实现了supports() 方法?如果它为 UsernamePasswordAuthenticationToken 类返回 false,则永远不会要求它处理过滤器创建的身份验证令牌。
  • 它甚至没有进入支持方法...
  • @Override public boolean supports(Class extends Object> authentication) { return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); }
  • 看来您声明的过滤器实际上被忽略了。请参阅手册 (static.springsource.org/spring-security/site/docs/3.1.x/…) 了解如何替换命名空间配置创建的过滤器。

标签: spring authentication spring-security


【解决方案1】:

我终于可以工作了。

这是我的上下文文件:

    <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" />

如您所见,我也添加了一些内容。

为了修复它,我删除了自动配置属性,取消了过滤器的注释,并正确定义了它们。

对于想要快速了解它的作用的其他人,这里是流程:

  1. PRE_AUTH_FILTER 将检查类似 SSO 的服务以预填充身份验证对象(如果已在 SSO 中进行身份验证)
  2. delegatingAuthenticationEntryPoint 然后将根据请求标头选择如何进行身份验证
  3. 两种方式是:
    • 自定义 LoginUrlAuthenticationEntryPoint
    • 自定义 BasicAuthenticationEntryPoint

当 PreAuth 使用我的 SSO 服务时,BasicAuth 和 LoginURLAuth 使用相同的 AuthenticationProvider。

希望对其他人有所帮助!

【讨论】:

    猜你喜欢
    • 2015-05-30
    • 2019-07-06
    • 2013-03-07
    • 2017-03-13
    • 2023-03-05
    • 2019-02-07
    • 2019-11-06
    • 2012-10-27
    • 2018-06-11
    相关资源
    最近更新 更多