Configuración de Spring Security 3.x para tener múltiples puntos de entrada

He estado usando Spring Security 3.x para manejar la autenticación de usuarios para mis proyectos, y hasta ahora, ha funcionado perfectamente.

Recientemente recibí los requisitos para un nuevo proyecto. En este proyecto, requiere 2 conjuntos de autenticación de usuario: uno para autenticar a los empleados en LDAP y otro para autenticar a los clientes en la base de datos. Estoy un poco perplejo sobre cómo configurar eso en Spring Security.

Mi idea inicial era crear una pantalla de inicio de sesión que tuviera los siguientes campos:

campo de botón de opción: para que los usuarios elijan si son empleados o clientes.j_username Campo de usuario.j_password campo de contraseña

Si el usuario selecciona "empleado", entonces quiero que Spring Security los autentique en LDAP; de lo contrario, la credencial se autenticará en la base de datos. Sin embargo, el problema es que el formulario se enviará a/j_spring_security_check y no hay forma de que envíe el campo del botón de opción a mi proveedor de autenticación personalizado implementado. Mi pensamiento inicial es que probablemente necesito dos URL de envío de formularios en lugar de confiar en el valor predeterminado/j_spring_security_check. Cada URL será manejada por diferentes proveedores de autenticación, pero no estoy seguro de cómo configurar eso en Spring Security.

Sé que en Spring Security, puedo configurar la autenticación alternativa, por ejemplo, si la autenticación LDAP falla, entonces recurrirá a la autenticación de la base de datos, pero esto no es lo que estoy buscando en este nuevo proyecto.

¿Alguien puede compartir cómo exactamente debería configurar esto en Spring Security 3.x?

Gracias.

ACTUALIZACIÓN - 28-01-2011 - Técnica de @ EasyAngel

Estoy tratando de hacer lo siguiente: -

El inicio de sesión del formulario de empleado se envía a/j_spring_security_check_for_employeeEl inicio de sesión del formulario del cliente se envía a/j_spring_security_check_for_customer

La razón por la que quiero 2 inicios de sesión de formulario diferentes es para permitirme manejar la autenticación de manera diferente en función del usuario, en lugar de hacer una autenticación alternativa. Es posible que el empleado y el cliente tengan la misma identificación de usuario, en mi caso.

Incorporé la idea de @ EasyAngel, pero tengo que reemplazar algunas clases obsoletas. El problema que estoy enfrentando actualmente es que ninguno de los procesos de filtro URLS parece registrado en Spring Security porque sigo obteniendoError 404: SRVE0190E: File not found: /j_spring_security_check_for_employee. Mi instinto es elspringSecurityFilterChain bean no está conectado correctamente, por lo tanto, mis filtros personalizados no se utilizan en absoluto.

Por cierto, estoy usando WebSphere y tengocom.ibm.ws.webcontainer.invokefilterscompatibility=true propiedad establecida en el servidor. Soy capaz de alcanzar el valor predeterminado/j_spring_security_check sin problemas.

Aquí está mi configuración de seguridad completa: -

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" 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.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <sec:http auto-config="true">
        <sec:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/welcome.jsp"
            always-use-default-target="true" />
        <sec:logout logout-success-url="/login.jsp" />
        <sec:intercept-url pattern="/employee/**" access="ROLE_EMPLOYEE" />
        <sec:intercept-url pattern="/customer/**" access="ROLE_CUSTOMER" />
        <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    </sec:http>

    <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
        <sec:filter-chain-map path-type="ant">
            <sec:filter-chain pattern="/**" filters="authenticationProcessingFilterForEmployee, authenticationProcessingFilterForCustomer" />
        </sec:filter-chain-map>
    </bean>

    <bean id="authenticationProcessingFilterForEmployee" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManagerForEmployee" />
        <property name="filterProcessesUrl" value="/j_spring_security_check_for_employee" />
    </bean>

    <bean id="authenticationProcessingFilterForCustomer" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManagerForCustomer" />
        <property name="filterProcessesUrl" value="/j_spring_security_check_for_customer" />
    </bean>

    <bean id="authenticationManagerForEmployee" class="org.springframework.security.authentication.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="employeeCustomAuthenticationProvider" />
            </list>
        </property>
    </bean>

    <bean id="authenticationManagerForCustomer" class="org.springframework.security.authentication.ProviderManager">
        <property name="providers">
            <list>
                <ref bean="customerCustomAuthenticationProvider" />
            </list>
        </property>
    </bean>

    <bean id="employeeCustomAuthenticationProvider" class="ss.EmployeeCustomAuthenticationProvider">
        <property name="userDetailsService">
            <bean class="ss.EmployeeUserDetailsService"/>
        </property>
    </bean>

    <bean id="customerCustomAuthenticationProvider" class="ss.CustomerCustomAuthenticationProvider">
        <property name="userDetailsService">
            <bean class="ss.CustomerUserDetailsService"/>
        </property>
    </bean>

    <sec:authentication-manager>
        <sec:authentication-provider ref="employeeCustomAuthenticationProvider" />
        <sec:authentication-provider ref="customerCustomAuthenticationProvider" />
    </sec:authentication-manager>

</beans>

Estoy comenzando una recompensa aquí porque parece que ya no puedo hacer que esto funcione durante varios días ... la frustración es la palabra. Espero que alguien señale los problemas, o si puede mostrarme una forma mejor o más limpia de manejar esto (en código).

Estoy usando Spring Security 3.x.

Gracias.

ACTUALIZACIÓN 29-01-2011 - Técnica de @Ritesh

De acuerdo, logré que el enfoque de @ Ritesh trabajara muy de cerca con lo que quería. Tengo el botón de radio que permite al usuario seleccionar si es cliente o empleado. Parece que este enfoque está funcionando bastante bien, con un problema ...

Si el empleado inicia sesión con la credencial correcta, se les permite ...TRABAJAR COMO ESPERADO.Si el empleado inicia sesión con una credencial incorrecta, no se les permite ...TRABAJAR COMO ESPERADO.Si el cliente inicia sesión con la credencial correcta, se les permite ...TRABAJAR COMO ESPERADO.Si el cliente inicia sesión con una credencial incorrecta, la autenticación recurre a la autenticación del empleado ...NO FUNCIONA. Esto es arriesgado porque si selecciono la autenticación del cliente y le doy la credencial de empleado, también permitirá que el usuario ingrese y esto no es lo que quiero.
    <sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
        <sec:logout logout-success-url="/login.jsp"/>
        <sec:intercept-url pattern="/employee/**" access="ROLE_EMPLOYEE"/>
        <sec:intercept-url pattern="/customer/**" access="ROLE_CUSTOMER"/>
        <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

        <sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter"/>
    </sec:http>


    <bean id="myAuthenticationFilter" class="ss.MyAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationFailureHandler" ref="failureHandler"/>
        <property name="authenticationSuccessHandler" ref="successHandler"/>
    </bean>

    <bean id="loginUrlAuthenticationEntryPoint"
          class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/login.jsp"/>
    </bean>

    <bean id="successHandler"
          class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <property name="defaultTargetUrl" value="/welcome.jsp"/>
        <property name="alwaysUseDefaultTargetUrl" value="true"/>
    </bean>

    <bean id="failureHandler"
          class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/login.jsp?login_error=1"/>
    </bean>


    <bean id="employeeCustomAuthenticationProvider" class="ss.EmployeeCustomAuthenticationProvider">
        <property name="userDetailsService">
            <bean class="ss.EmployeeUserDetailsService"/>
        </property>
    </bean>

    <bean id="customerCustomAuthenticationProvider" class="ss.CustomerCustomAuthenticationProvider">
        <property name="userDetailsService">
            <bean class="ss.CustomerUserDetailsService"/>
        </property>
    </bean>


    <sec:authentication-manager alias="authenticationManager">
        <sec:authentication-provider ref="customerCustomAuthenticationProvider"/>
        <sec:authentication-provider ref="employeeCustomAuthenticationProvider"/>
    </sec:authentication-manager>
</beans>

Aquí está mi configuración actualizada. Tiene que ser un pequeño ajuste que debo hacer para evitar que la autenticación retroceda, pero parece que no puedo entenderlo ahora.

Gracias.

ACTUALIZACIÓN - SOLUCIÓN a la técnica de @ Ritesh

Bien, creo que he resuelto el problema aquí. En vez de tenerEmployeeCustomAuthenticationProvider confiar en el valor predeterminadoUsernamePasswordAuthenticationToken, Yo creéEmployeeUsernamePasswordAuthenticationToken para ello, como el que creéCustomerUsernamePasswordAuthenticationToken paraCustomerCustomAuthenticationProvider. Estos proveedores anularán elsupports(): -

Clase CustomerCustomAuthenticationProvider

@Override
public boolean supports(Class<? extends Object> authentication) {
    return (CustomerUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}

Clase EmployeeCustomAuthenticationProvider

@Override
public boolean supports(Class<? extends Object> authentication) {
    return (EmployeeUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}

Clase MyAuthenticationFilter

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

    ...

    UsernamePasswordAuthenticationToken authRequest = null;

    if ("customer".equals(request.getParameter("radioAuthenticationType"))) {
        authRequest = new CustomerUsernamePasswordAuthenticationToken(username, password);

    }
    else {
        authRequest = new EmployeeUsernamePasswordAuthenticationToken(username, password);
    }

    setDetails(request, authRequest);

    return super.getAuthenticationManager().authenticate(authRequest);
}

... y WALAA! ¡Funciona perfectamente ahora después de varios días de frustración!

Con suerte, esta publicación podrá ayudar a alguien que está haciendo lo mismo que yo aquí.

Respuestas a la pregunta(4)

Su respuesta a la pregunta