Spring security 如何根据RequestHeaderAuthenticationFilter将身份验证管理器委托给特定的CustomUserDetailsService?

Spring security 如何根据RequestHeaderAuthenticationFilter将身份验证管理器委托给特定的CustomUserDetailsService?,spring-security,request-headers,pre-authentication,Spring Security,Request Headers,Pre Authentication,我在基于spring的应用程序中预验证用户时遇到问题 这是我的设想。我有两个CustomUserDetails服务,一个用于员工,一个用于客户。在我的服务器前面实现了一个代理,它在客户端请求的Http头中添加了两个头信息。让我们调用amHeader\u A和Header\u B 我希望spring security执行以下步骤: 获取标题\u A并在员工用户详细信息服务中使用它,以调用loadUserByUsername(字符串名称)方法。如果找到该用户,请对其进行身份验证,并授予他访问该应用程

我在基于spring的应用程序中预验证用户时遇到问题

这是我的设想。我有两个CustomUserDetails服务,一个用于员工,一个用于客户。在我的服务器前面实现了一个代理,它在客户端请求的Http头中添加了两个头信息。让我们调用am
Header\u A
Header\u B

我希望spring security执行以下步骤:

  • 获取
    标题\u A
    并在
    员工用户详细信息服务中使用它,以调用
    loadUserByUsername(字符串名称)
    方法。如果找到该用户,请对其进行身份验证,并授予他访问该应用程序的权限
  • 如果找不到该用户(未将其标识为员工),我希望该安全性获取
    标题并在
    CustomerUserDetails服务中使用它
  • 我尝试了以下方法,效果不错,但有变通方法(我不想这么做):

    
    
    这件事的作用如下:

  • 获取标题A并在EmployeeUserDetails服务中使用
  • 获取标题B并在EmployeeUserDetails服务中使用
  • 获取标题并在CustomerUserDetailsServie中使用
  • 获取标题并在CustomerUserDetailsServie中使用

  • 我所做的解决方法是验证头的长度(即修复),并返回;如果一个header get位于错误的UserDetails服务中

    如果您只想对header_A使用EmployeeUserDetails服务,而对header_B使用CustomerUserDetails服务,则可以创建多个AuthenticationManager实例,并将其连接到相应的筛选器中。例如:

    <sec:http use-expressions="true" access-denied-page="/denied.jsp" entry-point-ref="http403EntryPoint" authentication-manager-ref="authenticationManager">
        <sec:intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> 
        <sec:custom-filter after="PRE_AUTH_FILTER" ref="customerFilter" />
        <sec:custom-filter position="PRE_AUTH_FILTER" ref="employeeFilter" />
        <sec:logout delete-cookies="true" invalidate-session="true" logout-success-url="/" />
    </sec:http>
    <bean id="employeeFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
        <property name="principalRequestHeader" value="Header_A"/>
        <property name="authenticationManager" ref="employeeAuthenticationManager" />
        <property name="exceptionIfHeaderMissing" value="false"/>
    </bean> 
    <bean id="customerFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
        <property name="principalRequestHeader" value="Header_B"/>
        <property name="authenticationManager" ref="customerAuthenticationManager" />
        <property name="exceptionIfHeaderMissing" value="false"/>
    </bean>
    <bean id="employeePreAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="throwExceptionWhenTokenRejected" value="false" />
        <property name="preAuthenticatedUserDetailsService">
            <bean id="userDetailsServiceWrapper"  class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                <property name="userDetailsService" ref="employeeUserDetailsService"/>
            </bean>
        </property>
    </bean>
    <bean id="customerPreAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="throwExceptionWhenTokenRejected" value="false" />
        <property name="preAuthenticatedUserDetailsService">
            <bean id="userDetailsServiceWrapper"  class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                <property name="userDetailsService" ref="customerUserDetailsService"/>
            </bean>
        </property>
    </bean>
    <sec:authentication-manager id="authenticationManager">
        <sec:authentication-provider ref="customerPreAuthProvider" />
        <sec:authentication-provider ref="employeePreAuthProvider" />
    </sec:authentication-manager>
    <sec:authentication-manager id="customerAuthenticationManager">
        <sec:authentication-provider ref="customerPreAuthProvider" />
    </sec:authentication-manager>
    <sec:authentication-manager id="employeeAuthenticationManager">
        <sec:authentication-provider ref="employeePreAuthProvider" />
    </sec:authentication-manager>    
    <bean id="customerUserDetailsService" class="xxx.CustomerUserDetailsService"/>
    <bean id="employeeUserDetailsService" class="xxx.EmployeeUserDetailsService"/>
    
    
    
    请注意:

    • 如示例所示,在sec:authenticationmanager上使用id属性,因为使用alias将覆盖前面的bean定义并为其分配另一个指针
    • 如示例所示,确保更新employeeFilter和customerFilter中的authenticationManager引用
    • 如示例所示,确保指定指向可以对两个用户进行身份验证的AuthenticationManager的属性。这对于FilterSecurityInterceptor之类的东西是必要的