将 Spring Security 3.x 配置为具有多个入口点
我一直在使用Spring Security 3.x来处理我的项目的用户身份验证,到目前为止,它一直完美无缺。
我最近收到了一个新项目的要求。在此项目中,它需要 2 组用户身份验证:一组用于根据 LDAP 对员工进行身份验证,另一组用于根据数据库对客户进行身份验证。我对如何在Spring Security中配置它感到有些困惑。
我最初的想法是创建一个具有以下字段的登录屏幕:-
- 单选按钮字段 - 供用户选择他们是员工还是客户。
-
j_username
用户字段。 -
j_password
密码字段。
如果用户选择“员工”,那么我希望Spring Security根据LDAP对他们进行身份验证,否则凭据将根据数据库进行身份验证。但是,问题是表单将提交到,并且我无法将单选按钮字段发送到我实现的自定义身份验证提供程序。我最初的想法是,我可能需要两个表单提交URL,而不是依赖于默认的。每个URL将由不同的身份验证提供程序处理,但我不确定如何在Spring Security中配置它。/j_spring_security_check
/j_spring_security_check
我知道在Spring Security中,我可以配置回退身份验证,例如,如果LDAP身份验证失败,那么它将回退到数据库身份验证,但这不是我在这个新项目中要做的。
有人可以分享我应该如何在Spring Security 3.x中配置它吗?
谢谢。
更新 - 01-28-2011 - @EasyAngel的技术
我正在尝试执行以下操作:-
- 员工表单登录提交到
/j_spring_security_check_for_employee
- 客户表单登录提交至
/j_spring_security_check_for_customer
我想要2个不同的表单登录的原因是允许我根据用户以不同的方式处理身份验证,而不是执行回退身份验证。在我的情况下,员工和客户可能具有相同的用户ID。
我纳入了@EasyAngel的想法,但必须替换一些已弃用的类。我目前面临的问题是两个过滤进程都没有URLS似乎在Spring Security中注册,因为我一直在得到.我的直觉是豆子没有正确接线,因此根本没有使用我的自定义过滤器。Error 404: SRVE0190E: File not found: /j_spring_security_check_for_employee
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。
谢谢。
2011年01月29日 - @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
CustomerUsernamePasswordAuthenticationToken
CustomerCustomAuthenticationProvider
supports()
客户自定义身份验证提供程序类
@Override
public boolean supports(Class<? extends Object> authentication) {
return (CustomerUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
员工自定义身份验证提供程序类
@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);
}
...和瓦拉!经过几天的沮丧,它现在工作得很好!
希望这篇文章能够帮助那些正在做与我在这里相同事情的人。