一尘不染

将Spring Security 3.x配置为具有多个入口点

java

我一直在使用Spring Security 3.x来为我的项目处理用户身份验证,到目前为止,它已经完美地工作了。

我最近收到了一个新项目的要求。在此项目中,需要两套用户身份验证:一套用于根据LDAP验证员工,另一套用于根据数据库验证客户。我对如何在Spring Security中进行配置感到有些困惑。

我最初的想法是创建一个具有以下字段的登录屏幕:

  • 单选按钮字段-供用户选择是员工还是客户。
  • j_username 用户字段。
  • j_password 密码字段。
    如果用户选择“雇员”,那么我希望Spring Security根据LDAP对他们进行身份验证,否则,将根据数据库对凭据进行身份验证。但是,问题在于表单将提交到,/j_spring_security_check并且我无法将单选按钮字段发送给实现的自定义身份验证提供程序。我最初的想法是我可能需要两个表单提交URL,而不是依赖默认URL /j_spring_security_check。每个URL将由不同的身份验证提供程序处理,但是我不确定如何在Spring Security中进行配置。

我知道在Spring Security中,我可以配置回退身份验证,例如,如果LDAP身份验证失败,那么它将回退至数据库身份验证,但这不是我在这个新项目中要解决的问题。

有人可以分享我在Spring Security 3.x中应该如何配置它吗?

谢谢。

我正在尝试执行以下操作:

  • 员工表单登录提交给 /j_spring_security_check_for_employee
  • 客户表单登录提交给 /j_spring_security_check_for_customer
    我想要2种不同形式的登录的原因是允许我根据用户不同地处理身份验证,而不是进行后备身份验证。在我的情况下,员工和客户可能具有相同的用户ID。

我结合了@EasyAngel的想法,但必须替换一些不推荐使用的类。我目前面临的问题是,由于我不断获取,两个过滤器进程似乎都没有在Spring Security中注册URL Error 404: SRVE0190E: File not found: /j_spring_security_check_for_employee。我的直觉是springSecurityFilterChainBean接线不正确,因此根本没有使用我的自定义过滤器。

顺便说一下,我正在使用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 Security3.x。


阅读 328

收藏
2020-03-21

共1个答案

一尘不染

你无需创建/j_spring_security_check_for_employee/j_security_check_for_customer filterProcessingUrl

默认情况下,可以与单选按钮字段提示配合使用。

在定制登录中LoginFilter,你需要为员工和客户创建不同的令牌。

步骤如下:

  1. 使用默认值UsernamePasswordAuthenticationToken进行员工登录。

  2. 创建CustomerAuthenticationToken用于客户登录。进行扩展AbstractAuthenticationToken,以使其类类型不同于UsernamePasswordAuthenticationToken

  3. 定义自定义登录过滤器:

<security:http>
    <security:custom-filter position="FORM_LOGIN_FILTER" ref="customFormLoginFilter" />
</security:http>
  1. 在中customFormLoginFilter,请进行以下重写attemptAuthentication(伪代码):
if (radiobutton_param value employee) {
    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
    setDetails(whatever);
    return getAuthenticationManager().authenticate(authRequest);
} else if (radiobutton_param value customer) {
    CustomerAuthenticationToken authRequest = new CustomerAuthenticationToken(username, password);
    setDetails(whatever);
    return getAuthenticationManager().authenticate(authRequest);
}
  1. 支持重写supports方法。EmployeeCustomAuthenticationProviderUsernamePasswordAuthenticationToken

  2. 支持重写supports方法。CustomerCustomAuthenticationProviderCustomerAuthenticationToken

@Override
public boolean supports(Class<?> authentication) {
    return (CustomerAuthenticationToken.class.isAssignableFrom(authentication));
}
  1. authentication-manager以下两个提供商中使用:
<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref='employeeCustomAuthenticationProvider ' />
    <security:authentication-provider ref='customerCustomAuthenticationProvider ' />
</security:authentication-manager>
2020-03-21