使用Spring Security进行数据库和LDAP身份验证

时间:2013-03-18 06:16:17

标签: spring spring-security spring-ldap

我正在开发一个项目,我正在使用Spring Security,它可以很好地从DB验证用户。

现在我需要的是我想使用LDAP和保持现有数据库身份验证来验证用户。

另外,我不能通过使用Spring安全性来使用标准的LDAP身份验证方式,因为我只有一个函数调用来通过类似的方法来验证用户是否存在,

        com.company.ldap.Authentication  auth = new com.company.ldap.Authentication();
        int status = auth.authenticate(userName, userPassword);

如果我收到状态为1,那么用户将被验证,否则不会。

因此,对于这种情况,我创建了单独的URL“/ j_spring_facebook_security_check”(此处名称为facebook,但实际上是用于LDAP)

我的applicationContext-Security文件

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="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-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <security:http auto-config="true" use-expressions="true" access-denied-page="/accessDenied.jsp">

        <security:form-login login-page="/index.jsp"
            default-target-url="/jsp/home.jsp"
            authentication-failure-handler-ref="authenticationFailureHandler" />


        <security:intercept-url pattern="/jsp/listInBetweenPlaces.jsp"
            access="permitAll" />

        <security:intercept-url pattern="/jsp/home.jsp"
            access="permitAll" />


        <security:intercept-url pattern="/jsp/*"
            access="isAuthenticated()" />


        <security:logout logout-url="/j_spring_security_logout" logout-success-url="/index.jsp?logout=success" 
            invalidate-session="true"  />


    <security:custom-filter before="FORM_LOGIN_FILTER"
            ref="facebookAuthenticationFilter" />

    </security:http> 



    <bean id="facebookAuthenticationFilter" class="org.springframework.security.facebook.FacebookAuthenticationFilter">
      <property name="authenticationManager" ref="authenticationManager"/>

       <property  name = "authenticationSuccessHandler">
         <bean  class = "org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
           <property  name = "defaultTargetUrl"  value = "/jsp/home.jsp"  />
           <property  name = "alwaysUseDefaultTargetUrl"  value = "true"  />
         </bean>
       </property>

       <property  name = "authenticationFailureHandler">
        <bean  class = "org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
            <property  name = "defaultFailureUrl"  value = "/fb/failure.jsp"  />
        </bean>
       </property>

    </bean>




    <bean id="ldapAuthenticationProvider"  class="org.springframework.security.facebook.FacebookAuthenticationProvider">
        <property name="roles" value="ROLE_FACEBOOK_USER" />
    </bean>


    <security:authentication-manager alias="authenticationManager">  

        <security:authentication-provider user-service-ref="customUserDetailsService">
            <security:password-encoder hash="md5" />
        </security:authentication-provider>

        <security:authentication-provider ref="ldapAuthenticationProvider">
        </security:authentication-provider>

    </security:authentication-manager>




    <bean id="customUserDetailsService" class="com.abc.carpool.authentication.CustomUserDetailsService">
    </bean>

</beans>

FacebookAuthenticationFilter.java

public class FacebookAuthenticationFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {

    @Autowired
    CarpoolService carpoolService=null;

    public CarpoolService getCarpoolService() {
        return carpoolService;
    }
    public void setCarpoolService(CarpoolService carpoolService) {
        this.carpoolService = carpoolService;
    }


    public static final String DEFAULT_FILTER_PROCESS_URL = "/j_spring_facebook_security_check";

    private ApplicationContext ctx;
    protected FacebookAuthenticationFilter() {
        super(DEFAULT_FILTER_PROCESS_URL);
    }

    public Authentication attemptAuthentication(HttpServletRequest req,
            HttpServletResponse res) throws AuthenticationException,
            IOException, ServletException {


        HttpServletRequest request = (HttpServletRequest) req;

        String userName = request.getParameter("j_username");
        String userPassword = request.getParameter("j_password");


        System.out.println("Username and pswd is :"+userName + " " + userPassword);
        System.out.println("SYS PATH :"+System.getenv("MC_ENV_PATH"));

        User user = null;

        try{
            com.abc.ldap.Authentication  auth = new com.abc.ldap.Authentication();

            int status = auth.authenticate(userName, userPassword);

            //int status=2;
            if(status==1){

//CREATE NEW USER AND SAVE IN DB                    



                }

            }else{
                throw new UsernameNotFoundException("Incorrect Email Id or Password.");
            }

            System.out.println("status is :"+status);
        }catch (Exception e) {
            System.out.println("Exception is "+e.getMessage());
            e.printStackTrace();
            return null;
        }

        System.out.println("FacebookAuthenticationFilter.attemptAuthentication() :"+userName + " " + userPassword);     


        UsernamePasswordAuthenticationToken upatToken = new UsernamePasswordAuthenticationToken(userName, userPassword);
        AuthenticationManager authenticationManager = getAuthenticationManager();
        Authentication auth = authenticationManager.authenticate(upatToken);

        return auth;
    }

    public void setApplicationContext(ApplicationContext ctx)
            throws BeansException {
        this.ctx = ctx;
    }


}

FacebookAuthenticationProvider .java

public class FacebookAuthenticationProvider implements AuthenticationProvider {

    private String[] roles;

    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {

        System.out.println("FacebookAuthenticationProvider.authenticate()");

        return authentication;
    }

    public boolean supports(Class<? extends Object> authentication) {
        boolean supports = true;
        return supports;
    }

    public void setRoles(String[] roles) {
        this.roles = roles;
    }

    public String[] getRoles() {
        return roles;
    }
}

在上面的情况下,一切正常,Control将进入Filter类并使用LDAP验证用户,如果用户存在,那么我将用户一个副本保存到我的数据库,并希望继续正常流程。

实际上当我打电话时

Authentication auth = authenticationManager.authenticate(upatToken);

来自FacebookAuthenticationFilter,control,转到CustomUserDetailsS​​ervice类。

我的需求是CustomUserDetailsS​​ervice仅用于数据库身份验证,我不希望控制权去那里。

如何以一种很好的方式实现这一目标。

1 个答案:

答案 0 :(得分:0)

AuthenticationProvider.supports(Class<? extends Object> authentication)可以帮到你。此时,您将UsernamePasswordAuthenticationToken用于两种情况(DB和LDAP)。两个身份验证提供程序都支持此类型,因此使用它在LDAP的情况下,尝试添加自定义身份验证对象:

public class CustomLdapAuthenticationToken extends AbstractAuthenticationToken {

然后在FacebookAuthenticationFilter而不是UsernamePasswordAuthenticationToken中使用它。

更改FacebookAuthenticationProvider.supports(...)实施:

public boolean supports(Class<? extends Object> authentication) {
    boolean result = false;
    if(authentication instanceof CustomLdapAuthenticationToken) {
        result = true;
    }
    return result;
}

从此刻起,每个身份验证提供程序将仅处理相应的身份验证请求。