Настройка Spring Security 3.x для использования нескольких точек входа

Я использовал Spring Security 3.x для обработки аутентификации пользователей в моих проектах, и до сих пор он работал безупречно.

Недавно я получил требования для нового проекта. В этом проекте требуется 2 набора аутентификации пользователя: один для аутентификации сотрудников по LDAP, а другой для аутентификации клиента по базе данных. Я немного озадачен тем, как настроить это в Spring Security.

Моя первоначальная идея заключалась в том, чтобы создать экран входа в систему со следующими полями: -

  • поле переключателя - чтобы пользователи могли выбирать, являются ли они сотрудниками или клиенты.
  • j_username поле пользователя.
  • j_password поле пароля.

Если пользователь выбирает «сотрудник», то я хочу, чтобы Spring Security аутентифицировал его по LDAP, иначе учетные данные будут аутентифицированы против базы данных. Однако проблема заключается в том, что форма будет отправлена ​​в / j_spring_security_check , и у меня нет возможности отправить поле переключателя моему реализованному провайдеру пользовательской аутентификации. Моя первоначальная мысль заключается в том, что мне, вероятно, понадобятся два URL-адреса для отправки формы, а не полагаться на значение по умолчанию / j_spring_security_check . Каждый URL-адрес будет обрабатываться разными поставщиками аутентификации, но я не уверен, как настроить это в Spring Security.

Я знаю, что в Spring Security я могу настроить резервную аутентификацию, например, если аутентификация LDAP не удалась, тогда она будет вернуться к аутентификации в базе данных, но я не стремлюсь к этому в этом новом проекте.

Может кто-нибудь поделится, как именно мне это настроить в Spring Security 3.x?

Спасибо.


ОБНОВЛЕНИЕ - 28.01.2011 - техника @ EasyAngel

Я пытаюсь сделать следующее : -

  • Вход в форму сотрудника отправляется на / j_spring_security_check_for_employee
  • Вход в форму клиента отправляется на / j_spring_security_check_for_customer

Причина, по которой я хочу, чтобы два разных имени входа в форму позволяли мне обрабатывать аутентификацию по-разному. user, вместо выполнения резервной аутентификации. В моем случае возможно, что у сотрудника и клиента одинаковый идентификатор пользователя.

Я использовал идею @ EasyAngel, но мне пришлось заменить некоторые устаревшие классы. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что URL-адреса процессов фильтрации не кажутся зарегистрированными в Spring Security, потому что я продолжаю получать Ошибка 404: SRVE0190E: Файл не найден: / j_spring_security_check_for_employee . Мне кажется, что bean-компонент springSecurityFilterChain не подключен должным образом, поэтому мои пользовательские фильтры вообще не используются.

Кстати, я использую WebSphere, и у меня на сервере установлено свойство com.ibm.ws.webcontainer.invokefilterscompatibility = true . Я могу без проблем использовать значение по умолчанию / j_spring_security_check .

Вот моя полная конфигурация безопасности: -

<?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>

Я начинаю вознаграждение здесь, потому что я не могу заставить это работать для несколько дней уже ... разочарование - вот слово. Я надеюсь, что кто-то укажет на проблему (ы), или если вы покажете мне лучший или более чистый способ справиться с этим (в коде).

Я использую Spring Security 3.x.

Спасибо.


ОБНОВЛЕНИЕ 29.01.2011 - техника @Ritesh

Хорошо, мне удалось заставить подход @Ritesh работать очень близко к тому, что я хотел. У меня есть радиокнопка, которая позволяет пользователю выбирать, является ли он клиентом или сотрудником. Похоже, этот подход работает достаточно хорошо, но с одной проблемой ...

  • Если сотрудник входит в систему с правильными учетными данными, они могут быть разрешены в ... РАБОТАЕТ КАК ОЖИДАЕМЫЙ .
  • Если сотрудник ведет журналы с неправильными учетными данными, они не разрешены в ... РАБОТАЕТ КАК ОЖИДАЕТСЯ .
  • Если клиент входит в систему с правильными учетными данными, они могут быть разрешены в ... РАБОТАЕТ КАК ОЖИДАЕТСЯ .
  • Если клиент входит в систему с неправильными учетными данными, аутентификация возвращается к аутентификации служащего ... НЕ РАБОТАЕТ . Это рискованно, потому что, если я выберу аутентификацию клиента и введу учетные данные сотрудника, это также позволит пользователю войти, а это не то, что я хочу.
    <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>

Вот моя обновленная конфигурация. Мне нужно сделать небольшую настройку, чтобы предотвратить откат аутентификации, но я могу ' Кажется, сейчас я это понимаю.

Спасибо.

ОБНОВЛЕНИЕ - РЕШЕНИЕ для метода @Ritesh

Хорошо, я думаю, что решил проблему здесь. Вместо того, чтобы использовать EmployeeCustomAuthenticationProvider для использования по умолчанию UsernamePasswordAuthenticationToken , я создал для него EmployeeUsernamePasswordAuthenticationToken , точно так же, как и тот, который я создал для [1197808Tosername] [1197808OnService] для [1197808OnAuthentication], точно так же, как и тот, который я создал для [1197808Unsername] 1197810] CustomerCustomAuthenticationProvider . Затем эти поставщики переопределят supports () : -

Класс CustomerCustomAuthenticationProvider

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

Класс EmployeeCustomAuthenticationProvider

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

Класс 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);
}

... и WALAA! Теперь, после нескольких дней разочарований, он работает отлично!

Надеюсь, этот пост сможет помочь тому, кто делает то же самое, что и я.

64
задан PraveenKumar Lalasangi 27 September 2019 в 12:51
поделиться