복붙노트

[SPRING] 봄 보안 3.x를 구성하는 여러 진입 점을 가지고

SPRING

봄 보안 3.x를 구성하는 여러 진입 점을 가지고

내 프로젝트에 대한 사용자 인증을 처리하는 봄 보안 3.x를 사용하고있다, 지금까지, 그것은 완벽하게 일했다.

나는 최근에 새로운 프로젝트에 대한 요구 사항을 받았다. 이 프로젝트에서는 사용자 인증의 2 개 세트가 필요합니다 하나는 LDAP에 대해 직원을 인증하기 위해, 다른 하나는 데이터베이스에 대해 고객을 인증 할 수 있습니다. 나는 봄 보안에 그 구성 방법에 약간 난처한 해요.

내 초기 아이디어는 다음과 같은 필드가 로그인 화면을 만드는 것이 었습니다 : -

사용자가 "직원"을 선택하면, 나는 그렇지 않으면 자격 증명 데이터베이스에 대해 인증됩니다, 봄 보안 LDAP에 대해이를 인증하고 싶다. 그러나 문제는 / j_spring_security_check에 제출 될 양식이며 내 구현 사용자 인증 공급자의 라디오 버튼 필드를 보낼 수있는 방법은 없습니다. 내 최초의 생각은 아마 오히려 기본 / j_spring_security_check에 의존하지 않고 두 양식 제출 URL을 필요로합니다. 각 URL은 다른 인증 공급자에 의해 처리됩니다,하지만 난 봄 보안에 그것을 구성하는 방법을 모르겠어요.

나는 봄 보안에, 나는 LDAP 인증이 실패하면 다음 다시 데이터베이스 인증에 떨어질 것이다, 예를 들어, 인증을 후퇴 구성 할 수 있습니다 알고 있지만, 나는이 새로운 프로젝트에 대한 촬영하고있는 무슨이 아니다.

다른 사람과 공유 나는 봄 보안 3.x를이을 구성해야 할 수 정확히 어떻게?

감사합니다.

UPDATE - 2011년 1월 28일 - EasyAngel의 기술 @

나는 다음을 수행하려고 해요 : -

나는 2 개의 다른 형태의 로그인을 원하는 이유는 나를 대신 가을 - 다시 인증을하는, 다른 사용자를 기반으로 인증을 처리 할 수 ​​있도록하는 것입니다. 직원과 고객이 내 경우, 동일한 사용자 ID를 가지고있다.

나는 EasyAngel의 아이디어 @ 통합하지만, 일부 사용되지 않는 클래스를 교체해야합니다. SRVE0190E : 파일을 찾을 수 없습니다 : / j_spring_security_check_for_employee 나는 오류 404가 계속 때문에 현재 직면하고있어 문제는 URL이 봄 보안에 등록 된 것 같다 어느 필터 프로세스이다. 내 직감은 springSecurityFilterChain 콩 따라서 내 사용자 정의 필터가 전혀 사용되지는 유선되지이다.

그런데, 나는에서는 WebSphere를 사용하고 난 서버에서 com.ibm.ws.webcontainer.invokefilterscompatibility = 진정한 속성 집합을해야합니까. 나는 문제없이 기본 / 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>

이미 며칠 동안이 작업을 얻이 수없는 것 때문에 여기에 현상금을 시작 했어 ... 좌절 단어입니다. 나는 누군가가 문제 (들)을 가리 킵니다 희망, 또는 해요 당신이 나에게 (코드)이 처리하는 더 나은 또는 청소기 방법을 보여 할 수 있습니다.

나는 봄 보안 3.x를 사용하고

감사합니다.

UPDATE 2011년 1월 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>

여기 내 업데이트 된 구성입니다. 내가 인증 낙하 등을 방지하기 위해 수행해야 할 몇 가지 정말 작은 비틀기로 가지고 있지만 지금은 그것을 알아낼 수 없습니다.

감사합니다.

UPDATE - 솔루션 Ritesh의 기술 @

좋아, 내가 여기에 문제를 해결했다 생각합니다. 대신 기본이 UsernamePasswordAuthenticationToken에 의존 EmployeeCustomAuthenticationProvider을 갖는, 난 그냥 CustomerCustomAuthenticationProvider에 대한 CustomerUsernamePasswordAuthenticationToken을 만든처럼 그것을 EmployeeUsernamePasswordAuthenticationToken을 만들었습니다. 이러한 공급자는 지지대 ()를 재정의합니다 -

고객 CustomAuthenticationProvider 클래스

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

직원 CustomAuthenticationProvider 클래스

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

IAuthenticationFilter 클래스

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! 그것은 좌절의 몇 일 후에 완벽하게 지금 작동합니다!

바라건대,이 게시물은 내가 여기와 같은 일을하고 누군가를 도울 수있을 것입니다.

해결법

  1. ==============================

    1.당신은 / j_spring_security_check_for_employee 및 / j_security_check_for_customer filterProcessingUrl을 만들 필요가 없습니다.

    당신은 / j_spring_security_check_for_employee 및 / j_security_check_for_customer filterProcessingUrl을 만들 필요가 없습니다.

    기본 중 하나는 라디오 버튼 필드 아이디어와 잘 작동합니다.

    사용자 정의 로그인 LoginFilter에서는 직원과 고객을위한 다른 토큰을 생성해야합니다.

    다음 단계는 다음과 같습니다

  2. ==============================

    2.당신은 몇 가지의 AuthenticationProcessingFilter 필터를 정의 할 수 있습니다. 그들 각각 / j_security_check_for_employee 및 / j_security_check_for_customer 같은 다른 URL을 가질 수 있습니다. 다음은이 아이디어를 보여줍니다 보안 애플리케이션 컨텍스트의 예입니다 :

    당신은 몇 가지의 AuthenticationProcessingFilter 필터를 정의 할 수 있습니다. 그들 각각 / j_security_check_for_employee 및 / j_security_check_for_customer 같은 다른 URL을 가질 수 있습니다. 다음은이 아이디어를 보여줍니다 보안 애플리케이션 컨텍스트의 예입니다 :

    <bean id="myfilterChainProxy" class="org.springframework.security.util.FilterChainProxy">
         <security:filter-chain-map pathType="ant">
             <security:filter-chain pattern="/**" filters="authenticationProcessingFilterForCustomer, authenticationProcessingFilterForEmployee, ..." />
         </security:filter-chain-map>
    </bean>
    
    
    <bean id="authenticationProcessingFilterForCustomer" class="org.springframework.security.web.authentication.AuthenticationProcessingFilter">
        <property name="authenticationManager" ref="authenticationManagerForCustomer"/>
        <property name="filterProcessesUrl" value="/j_security_check_for_customer"/>
    </bean>
    
    <bean id="authenticationProcessingFilterForEmployee" class="org.springframework.security.web.authentication.AuthenticationProcessingFilter">
        <property name="authenticationManager" ref="authenticationManagerForEmployee"/>
        <property name="filterProcessesUrl" value="/j_security_check_for_employee"/>
    </bean>
    
    <bean id="authenticationManagerForCustomer" class="org.springframework.security.authentication.ProviderManager">
        <property name="providers">
            <list>
                <bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
                    <property name="userDetailsService">
                        <ref bean="customerUserDetailsServiceThatUsesDB"/>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
    
    <bean id="authenticationManagerForEmployee" class="org.springframework.security.authentication.ProviderManager">
        <property name="providers">
            <list>
                <bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                    <property name="userDetailsService">
                        <ref bean="employeeUserDetailsServiceThatUsesLDAP"/>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
    

    DB의 인증 및 LDAP을위한 - 당신이 볼 수 있듯이,이 시나리오에서 당신은 또한 다른 UserDetailServices 있습니다.

    나는 (서로 다른 인증 전략을 사용하는 경우 특히) 고객과 직원에 대해 서로 다른 인증 URL이 좋은 아이디어라고 생각합니다. 당신은 그들을 위해 다른 로그인 페이지를 가질 수 있습니다.

  3. ==============================

    3.당신은 DB에서이 정보를 저장할 수 있습니다. 예를 들어, 당신은 사용자 테이블에 ldap_auth라는 컬럼을 가질 수 있습니다. 당신은 (예를 들어) 내 다른 답변을 볼 수 있습니다 :

    당신은 DB에서이 정보를 저장할 수 있습니다. 예를 들어, 당신은 사용자 테이블에 ldap_auth라는 컬럼을 가질 수 있습니다. 당신은 (예를 들어) 내 다른 답변을 볼 수 있습니다 :

    봄 로그인 폼 예제

    주의 깊게 UserService 클래스를 보면, 당신은 내가 실제로 LDAP 플래그를 테스트하거나 LDAP 또는 데이터베이스에서 사용자 암호를 취할 것을 알 수 있습니다.

  4. ==============================

    4.그것은 나를 다시입니다 :)이 같은 필터를 사용하려고 수 :

    그것은 나를 다시입니다 :)이 같은 필터를 사용하려고 수 :

    <sec:http auto-config="true">
        ...
        <sec:custom-filter ref="authenticationProcessingFilterForCustomer" after="FIRST"/>
        <sec:custom-filter ref="authenticationProcessingFilterForEmployee" after="FIRST"/>
    </sec:http>
    

    대신 콩 springSecurityFilterChain을 정의.

  5. ==============================

    5.내가 여기에 XML 구성에 익숙하지 않은 사람들을 돕기 위해 동일한 기술을 구현하는 자바 구성 방법을 쓰고 싶어하지만로서 내가 자바 구성 코드의 같은 긴 대답이 스레드의 아름다움을 납치하고 싶지 않아요.

    내가 여기에 XML 구성에 익숙하지 않은 사람들을 돕기 위해 동일한 기술을 구현하는 자바 구성 방법을 쓰고 싶어하지만로서 내가 자바 구성 코드의 같은 긴 대답이 스레드의 아름다움을 납치하고 싶지 않아요.

    (기반 주석) 자바 구성과 동일 달성하고자하는 사람들은 내 자신이 링크가 아래에 주어진 질문에 대한 답변과 또한 당신이 대답의 코드 내 GitHub의 저장소 링크를 찾을 수 있습니다 참조 할 수 있습니다.

    주석 기반 구성 코드에 대한 참조 다른 UsernamePasswordAuthToken 여러 AuthenticationProvider에는 대체 인증없이 다른 로그인 양식을 인증하기

  6. from https://stackoverflow.com/questions/4783063/configuring-spring-security-3-x-to-have-multiple-entry-points by cc-by-sa and MIT license