配置的Spring Security 3.X有多个入口点 [英] Configuring Spring Security 3.x to have multiple entry points

查看:142
本文介绍了配置的Spring Security 3.X有多个入口点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been using Spring Security 3.x for handling user authentication for my projects, and so far, it has worked flawlessly.

我最近收到了一个新项目的要求。在这个项目中,它需要2套用户身份验证:一个对LDAP认证的员工,另一个对数据库进行身份验证的客户。我对如何配置Spring Security的有点难倒。

I recently received the requirements for a new project. In this project, it requires 2 sets of user authentication: one to authenticate employees against LDAP, and another to authenticate customer against database. I'm a little stumped on how to configure that in Spring Security.

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

My initial idea was to create a login screen that has the following fields:-


  • 单选按钮字段 - 供用户选择,无论是员工或客户

  • 为j_username 用户字段。

  • 为j_password 密码字段。

  • radio button field - for users to choose whether they are employees or customers.
  • j_username user field.
  • j_password password field.

如果用户选择员工,那么我想Spring Security的打击LDAP验证它们,否则将凭据对数据库进行身份验证。然而,问题的形式将被提交给 / j_spring_security_check ,有没有办法,我的单选按钮领域发到我实现的自定义身份验证提供者。我最初的想法是,我可能需要两个表单提交的URL,而不是依赖于默认 / j_spring_security_check 。每个URL都会被不同的身份验证提供者来处理,但我不知道如何配置Spring Security的。

If the user selects "employee", then I want Spring Security to authenticate them against LDAP, otherwise the credential will be authenticated against database. However, the problem is the form will be submitted to /j_spring_security_check and there's no way for me to send the radio button field to my implemented custom authentication provider. My initial thought is I probably need two form submission URLs rather than relying on the default /j_spring_security_check. Each URL will be handled by different authentication providers, but I'm not sure how to configure that in Spring Security.

我知道Spring Security的,我可以配置回落验证,例如,如果LDAP认证失败,那么它会回落到数据库认证,但这不是我拍摄的在这个新项目。

I know in Spring Security, I can configure fall back authentication, for example if LDAP authentication fails, then it will fall back to database authentication, but this is not what I'm shooting for in this new project.

有人可以分享究竟如何,我应该在春季安全3.X配置此?

Can someone share how exactly I should configure this in Spring Security 3.x?

感谢您。

更新 - 2011年1月28日 - @ EasyAngel的技术

我试图做到以下几点: -

I'm trying to do the following:-


  • 员工登录表单提交给 / j_spring_security_check_for_employee

  • 客户登录表单提交给 / j_spring_security_check_for_customer

  • Employee form login submits to /j_spring_security_check_for_employee
  • Customer form login submits to /j_spring_security_check_for_customer

我要2个不同的形式登录的原因是为了让我来处理不同的身份验证基于用户,而不是做一回退认证。这可能是员工和客户有相同的用户ID,在我的情况。

The reason I want 2 different form logins is to allow me to handle the authentication differently based on the user, instead of doing a fall-back authentication. It is possible that employee and customer have same user ID, in my case.

我注册@ EasyAngel的想法,但必须更换某些德precated类。我目前面临的问题是没有过滤的过程网址似乎是因为我不断收到注册的Spring Security 错误404:SRVE0190E:找不到文件:/ j_spring_security_check_for_employee 。我的直觉是 springSecurityFilterChain 豆不正确接线,因此我的自定义过滤器不使用的。

I incorporated @EasyAngel's idea, but have to replace some deprecated classes. The problem I'm currently facing is neither filter processes URLS seem registered in Spring Security because I keep getting Error 404: SRVE0190E: File not found: /j_spring_security_check_for_employee. My gut feeling is the springSecurityFilterChain bean is not wired properly, thus my custom filters are not used at all.

顺便说一句,我使用WebSphere和我确实有 com.ibm.ws.webcontainer.invokefilterscompatibility = TRUE 属性设置服务器。我能击中默认 / j_spring_security_check 没有问题。

By the way, I'm using WebSphere and I do have com.ibm.ws.webcontainer.invokefilterscompatibility=true property set in the server. I'm able to hit the default /j_spring_security_check without problem.

下面是我的完整的安全配置: -

Here's my complete security configuration:-

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

我在这里开始一个赏金,因为我似乎无法得到这个工作了好几天......已经无奈这个词。我希望有人会指出这个问题上,或者如果你能告诉我一个更好的或较清洁的方式来处理这个问题(在code)。

I'm starting a bounty here because I can't seem to get this working for several days already... frustration is the word. I'm hoping someone will point out the problem(s), or if you can show me a better or cleaner way to handle this (in code).

我使用的Spring Security 3.x的

I'm using Spring Security 3.x.

感谢您。

更新2011年1月29日 - @仅限Ritesh的技术

好吧,我设法@仅限Ritesh的做法非常密切地合作,以我想要的东西。我有一个允许用户选择他们是否是客户或员工的单选按钮。看起来这种方法的工作还算不错,有一个问题...

Okay, I managed to get @Ritesh's approach to work very closely to what I wanted. I have the radiobutton that allows user to select whether they are customer or employee. It seems like this approach is working fairly well, with one problem...


  • 如果员工与正确的凭据登录时,他们被允许在... 按预期

  • 如果员工有错误的凭据登录时,他们没有在... 工作使得如预期

  • 如果在右凭证客户登录,他们... 的作品被允许如预期

  • 如果在错误的凭据客户登录,认证回落到员工的身份验证... 不工作。这是有风险的,因为如果我选择的客户身份验证,并冲它的员工凭证后,它将允许用户在太多,这不是我想要的。

  • If employee logs in with right credential, they are allowed in... WORK AS EXPECTED.
  • If employee logs in with wrong credential, they are not allowed in... WORK AS EXPECTED.
  • If customer logs in with right credential, they are allowed in... WORK AS EXPECTED.
  • If customer logs in with wrong credential, the authentication falls back to employee authentication... DOESN'T WORK. This is risky because if I select customer authentication, and punch it the employee credential, it will allow the user in too and this is not what I want.
    <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>

下面是我更新的配置。它必须是一些非常小的调整,我需要做的prevent认证回落,但我似乎不能现在就看着办吧。

Here's my updated configuration. It has to be some really small tweak I need to do to prevent the authentication fall back but I can't seem to figure it out now.

感谢您。

更新 - 解决方案,以@仅限Ritesh的技术

好吧,我想我已经在这里解决了这个问题。与其让 EmployeeCustomAuthenticationProvider 依赖于默认的 UsernamePasswordAut​​henticationToken ,我创建 EmployeeUsernamePasswordAut​​henticationToken 它,就像一个我创建的 CustomerUsernamePasswordAut​​henticationToken CustomerCustomAuthenticationProvider 。然后,这些供应商将覆盖支持(): -

Okay, I think I have solved the problem here. Instead of having EmployeeCustomAuthenticationProvider to rely on the default UsernamePasswordAuthenticationToken, I created EmployeeUsernamePasswordAuthenticationToken for it, just like the one I created CustomerUsernamePasswordAuthenticationToken for CustomerCustomAuthenticationProvider. These providers will then override the 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!它的工作原理后,无奈的几天完美吧!

... and WALAA! It works perfectly now after several days of frustration!

希望这篇文章可以帮助别人为我在这里谁在做同样的事情。

Hopefully, this post will be able to help somebody who is doing the same thing as I am here.

推荐答案

您不必创建 / j_spring_security_check_for_employee / j_security_check_for_customer filterProcessingUrl

默认一会工夫只是单选按钮字段的想法很好。

The default one will work just fine with radio button field idea.

在自定义登录 LoginFilter ,你需要为员工和客户不同的令牌。

In the custom login LoginFilter, you need to create different tokens for employee and customer.

下面的步骤是:


  1. 使用默认的 UsernamePasswordAut​​henticationToken 员工登录。

有关客户登录创建 CustomerAuthenticationToken 。延长 AbstractAuthenticationToken ,以便其类类型有别于 UsernamePasswordAut​​henticationToken

Create CustomerAuthenticationToken for customer login. Extend AbstractAuthenticationToken so that its class type is distinct from UsernamePasswordAuthenticationToken.

定义一个自定义登录过滤器:

Define a custom login filter:

<security:http>
    <security:custom-filter position="FORM_LOGIN_FILTER" ref="customFormLoginFilter" />
</security:http>


  • customFormLoginFilter ,覆盖 attemptAuthentication 如下(伪code):

  • In customFormLoginFilter, override attemptAuthentication as follows (pseudo code):

    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);
    }
    


  • 覆盖支持方法 EmployeeCustomAuthenticationProvider 来支持 UsernamePasswordAut​​henticationToken

    覆盖支持方法 CustomerCustomAuthenticationProvider 来支持 CustomerAuthenticationToken

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


  • 使用两个提供商认证管理器

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref='employeeCustomAuthenticationProvider ' />
        <security:authentication-provider ref='customerCustomAuthenticationProvider ' />
    </security:authentication-manager>
    


  • 这篇关于配置的Spring Security 3.X有多个入口点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆