当前位置: 首页 > 面试题库 >

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

翟功
2023-03-14
问题内容

我一直在使用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。


问题答案:

你无需创建/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>


 类似资料:
  • 对集群设置有点困惑: > Zookeeper可以通过配置myid(1,2,3...)将其设置为群集例如,在zoo.cfg文件中具有zookeeper1:2888:3888、zookeeper2:2889:3889 对于Kafka,在server.properties文件中,是否必须为参数zookeeper.connect指定zookeeper服务器的完整列表,还是只要1就足够了?有什么不同吗?我见

  • 当从外部访问时,由于没有有效的CA,我得到了这个错误 验证深度为32 CONNECTED(00000003)不能使用SSL_get_servername深度=0 O=Acme Co,CN=库伯内特斯In的控制器伪造证书验证错误:编号=18:自签名证书验证返回:1深度=0 O=Acme Co,CN=伯库内特斯In的控制器伪造证书验证返回:1---证书链0 s: O=Acme Co,CN=库伯内特斯I

  • 我有一个XSD文件,我想在其中放置几个图表,以及服务的描述。添加时 我得到错误:“多个根标记” 如果我这样写: 我得到错误: 发现以元素{开头的内容无效http://www.w3.org/2001/XMLSchema“:架构}。其中一个{”http://www.w3.org/2001/XMLSchema“:simpleType,”http://www.w3.org/2001/XMLSchema“:

  • 问题内容: 我创建了一个小部件,该小部件显示一个简单的textview,可在配置活动中将其作为Edittext编辑。我将输入的文本与共享的首选项一起保存,因此用户可以点击小部件来编辑文本,并且已经输入的文本将出现在edittextfield中。我的问题是这个。我希望用户能够添加多个窗口小部件,但是当添加第二个窗口小部件时,将从共享首选项中加载与其他窗口小部件中相同的文本。并且,当在widget上被

  • 1-我有一个带有Spring Boot的API,我需要配置两个DBMS(MySQL和Postgres)。 2-对于每个DBMS,我需要配置不同的配置文件。(Dev,Prod) 遵循我的MySQL配置类: 我以为我的出口是: 重要: 当我将配置文件配置为连接到我的MySQL Dev数据库时,我只想连接到它。我想要同样的结果,当它是MySQL的Prod的基础时。 当我将配置文件配置为连接到我的Post