положение, но кажется, что это неправильно).
ользую 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?
Спасибо.
ОБНОВЛЕНИЕ - 01-28-2011 - @ EasyAngel's техника
Я пытаюсь сделать следующее: -
Форма входа сотрудника/j_spring_security_check_for_employee
Форма входа для клиента/j_spring_security_check_for_customer
Причина, по которой я хочу иметь два разных входа в систему, заключается в том, что я могу по-разному обрабатывать аутентификацию в зависимости от пользователя, а не выполнять резервную аутентификацию. Возможно, у сотрудника и клиента одинаковый идентификатор пользователя, в моем случае.
Я включил идею @ EasyAngel, но должен заменить некоторые устаревшие классы. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что ни один из процессов фильтрации не выглядит зарегистрированным в Spring Security, посколькуError 404: SRVE0190E: File not found: /j_spring_security_check_for_employee
, Мое внутреннее чувствоspringSecurityFilterChain
bean не подключен должным образом, поэтому мои пользовательские фильтры не используются вообще.
Кстати, я использую 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.
Спасибо.
ОБНОВЛЕНИЕ 01-29-2011 - @ Техника Ритеша
Хорошо, мне удалось заставить подход @ 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
для него, как тот, который я создалCustomerUsernamePasswordAuthenticationToken
за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 class
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);
}
... и ВАЛАА! Теперь он отлично работает после нескольких дней разочарования!
Надеюсь, этот пост сможет помочь кому-то, кто делает то же самое, что и я здесь.