繁体   English   中英

具有Spring Security的双重身份验证(带有表单登录和请求)

[英]Double authentication with spring security (with form-login and request)

我目前正在从事一个涉及GWT 2.5 + Spring 3.1 + Hibernate 3.10的项目。

该Web应用程序目前正在生产中,并具有受保护的资源。 为了安全起见,我们将Spring Security 3.1与LDAP认证一起使用。

当前,我们有一个表单登录名,其中填写用户名和密码,然后如果一切正常,则重定向到适当的html页(在成功处理程序中),否则,我们重定向到失败页(由于失败处理程序)。

现在,客户端希望保留此功能并添加新功能,该功能包括直接在URL中添加用户名和密码,而无需通过表单登录。 如果凭据确定,这将成功进行身份验证,否则它将重定向到失败页面。

我已经阅读了很多有关该主题的内容,但无法使某些内容正常工作。

这是我现有的spring-security.xml文件:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"   
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd">

<!-- ================================================== -->
<!-- SECURITE                                           -->
<!-- ================================================== --> 

<security:http pattern="/jsp/static/**" security="none"/>
<security:http pattern="/PIE.htc" security="none"/>
<security:http pattern="/ConsultationAccords.css" security="none"/>

    <!--Allow everyone to access the JSP login page -->
    <security:intercept-url pattern="/app/auth/**" access="permitAll"/>
    <security:intercept-url pattern="/jsp/*" access="permitAll"/>

    <!-- Limitation  d'accès aux différentes partie de l'appli, les pattern sont basés sur les déclaration dans le fichier web.xml  -->     
    <security:intercept-url pattern="/consultationaccords/**" access="isAuthenticated()"/>
    <security:intercept-url pattern="/DownloadCourrierServ" access="isAuthenticated()"/>
    <security:intercept-url pattern="/*.gupId" access="isAuthenticated()"/>
    <security:intercept-url pattern="/DownloadServ" access="isAuthenticated()"/>
    <security:intercept-url pattern="/ConsultationAccords.html" access="isAuthenticated()"/>    
    <security:intercept-url pattern="/ExportServ" access="isAuthenticated()"/>      
    <security:intercept-url pattern="/ManuelUtilisateurServ" access="isAuthenticated()"/>

    <security:intercept-url pattern="/**" access="denyAll" />
    <!-- If the user is authorized, he will be redirected to the success-handler.
            The sucess-handler is responsible of interpreting what to do next.
            Same principle with the failure-handler -->         
    <security:form-login authentication-success-handler-ref="authenticationSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler" />

    <!-- These are the login and logout URLs -->    
    <security:logout invalidate-session="true" logout-success-url="/app/auth/login" logout-url="/app/auth/logout"/>

    <security:session-management invalid-session-url="/app/auth/login"/>
</security:http>

<!-- Point d'entrée pour indiquer à l'utilisateur qu'il doit s'authentifier d'abord -->     
<beans:bean id="authenticationEntryPoint" class="fr.gouv.travail.consultationAccords.server.auth.GAAuthenticationEntryPoint" />

<!-- Handler appelé si l'utilisateur a été authetifié avec succès -->       
<beans:bean id="authenticationSuccessHandler" class="fr.gouv.travail.consultationAccords.server.auth.GAAuthenticationSuccessHandler"/>

<!-- Handler appelé si l'authetification de l'utilisateur  a échoué --> 
<beans:bean id="authenticationFailureHandler" class="fr.gouv.travail.consultationAccords.server.auth.GAAuthenticationFailureHandler"/>

<!-- ================================================== -->
<!-- *********************************                  -->
<!-- ================================================== --> 

<security:authentication-manager>
    <security:authentication-provider ref='ldapAuthProvider' />
</security:authentication-manager>

<!-- ================================================== -->
<!-- CONNEXION AU LDAP      -->
<!-- ================================================== -->

<bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <constructor-arg value="ldap://${ldap.server_ip}:${ldap.server_port}"/>
    <property name="userDn" value="${ldap.user_reader_account}" />
    <property name="password" value="${ldap.password_reader_account}" />
</bean>

<!-- ================================================== -->
<!-- AUTHENTIFICATION + AUTORISATION      -->
<!-- ================================================== --> 

<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">

    <constructor-arg>
        <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <constructor-arg ref="contextSource" />
            <property name="userSearch">
                <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
                  <constructor-arg index="0" value="${ldap.user_base_search}"/>
                  <constructor-arg index="1" value="(uid={0}@${ldap.domain_name})"/>
                  <constructor-arg index="2" ref="contextSource" />
                </bean>
            </property>
        </bean>
    </constructor-arg>

     <constructor-arg>
        <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
            <constructor-arg ref="contextSource" />
            <constructor-arg value="${ldap.group_base_search}" />
            <property name="groupSearchFilter" value="(uniqueMember={0})"/>
            <property name="rolePrefix" value="ROLE_"/>
            <property name="searchSubtree" value="true"/>
            <property name="convertToUpperCase" value="true"/>
            <property name="groupRoleAttribute" value="${ldap.group_role_attribute}"/>
        </bean>
    </constructor-arg>
</bean>

我的web.xml的相关部分

    <!-- The Spring Security Filter Chain -->
<filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<!-- Pay attention to the url-pattern -->
<filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Front Controller for all Spring based servlets -->
<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext.xml
            /WEB-INF/spring-servlet.xml
        </param-value>
     </init-param> 
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Don't forget to declare a spring-servlet.xml -->
<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/app/*</url-pattern>
</servlet-mapping>

这是我所做的:

  1. 声明并设置一个为UsernamePasswordAuthenticationFilter的bean(具有成功处理程序,失败处理程序,身份验证管理器,usernameParameter和passwordParameter)

  2. 将其添加到security-http标签+ FIRST的配置位置

  3. 我的web.xml包含springSecurityFilterChain

我的spring-security.xml修改为:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"   
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd">

<!-- ================================================== -->
<!-- SECURITE                                           -->
<!-- ================================================== --> 

<security:http pattern="/jsp/static/**" security="none"/>
<security:http pattern="/PIE.htc" security="none"/>
<security:http pattern="/ConsultationAccords.css" security="none"/>
<security:http pattern="/app/auth/images/**" security="none"/>

    <security:custom-filter ref="requestAuthenticationFilter" position="FIRST" />

    <!--Allow everyone to access the JSP login page -->
    <security:intercept-url pattern="/app/auth/**" access="permitAll"/>
    <security:intercept-url pattern="/jsp/*" access="permitAll"/>

    <!-- Limitation  d'accès aux différentes partie de l'appli, les pattern sont basés sur les déclaration dans le fichier web.xml  -->     
    <security:intercept-url pattern="/consultationaccords/**" access="isAuthenticated()"/>
    <security:intercept-url pattern="/DownloadCourrierServ" access="isAuthenticated()"/>
    <security:intercept-url pattern="/*.gupId" access="isAuthenticated()"/>
    <security:intercept-url pattern="/DownloadServ" access="isAuthenticated()"/>
    <security:intercept-url pattern="/ConsultationAccords.html" access="isAuthenticated()"/>    
    <security:intercept-url pattern="/ExportServ" access="isAuthenticated()"/>      
    <security:intercept-url pattern="/ManuelUtilisateurServ" access="isAuthenticated()"/>

    <security:intercept-url pattern="/**" access="denyAll" />
    <security:form-login authentication-success-handler-ref="authenticationSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler" />

    <!-- These are the login and logout URLs -->    
    <security:logout invalidate-session="true" logout-success-url="/app/auth/login" logout-url="/app/auth/logout" />

    <security:session-management invalid-session-url="/app/auth/login"/>
</security:http>

<beans:bean id="requestAuthenticationFilter" class="fr.gouv.travail.consultationAccords.server.auth.RequestAuthenticationFilter">
    <beans:property name="usernameParameter" value="${ldap.user_request_param_direct_logging}" />
    <beans:property name="passwordParameter" value="${ldap.password_request_param_direct_logging}" />
    <beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
    <beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
    <beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>

<!-- Point d'entrée pour indiquer à l'utilisateur qu'il doit s'authentifier d'abord -->     
<beans:bean id="authenticationEntryPoint" class="fr.gouv.travail.consultationAccords.server.auth.GAAuthenticationEntryPoint" />

<!-- Handler appelé si l'utilisateur a été authetifié avec succès -->       
<beans:bean id="authenticationSuccessHandler" class="fr.gouv.travail.consultationAccords.server.auth.GAAuthenticationSuccessHandler"/>

<!-- Handler appelé si l'authetification de l'utilisateur  a échoué --> 
<beans:bean id="authenticationFailureHandler" class="fr.gouv.travail.consultationAccords.server.auth.GAAuthenticationFailureHandler"/>

<!-- ================================================== -->
<!-- *********************************                  -->
<!-- ================================================== --> 

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

<!-- ================================================== -->
<!-- CONNEXION AU LDAP      -->
<!-- ================================================== -->

<bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <constructor-arg value="ldap://${ldap.server_ip}:${ldap.server_port}"/>
    <property name="userDn" value="${ldap.user_reader_account}" />
    <property name="password" value="${ldap.password_reader_account}" />
</bean>

<!-- ================================================== -->
<!-- AUTHENTIFICATION + AUTORISATION      -->
<!-- ================================================== --> 

<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">

    <constructor-arg>
        <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <constructor-arg ref="contextSource" />
            <property name="userSearch">
                <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
                  <constructor-arg index="0" value="${ldap.user_base_search}"/>
                  <constructor-arg index="1" value="(uid={0}@${ldap.domain_name})"/>
                  <constructor-arg index="2" ref="contextSource" />
                </bean>
            </property>
        </bean>
    </constructor-arg>

     <constructor-arg>
        <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
            <constructor-arg ref="contextSource" />
            <constructor-arg value="${ldap.group_base_search}" />
            <property name="groupSearchFilter" value="(uniqueMember={0})"/>
            <property name="rolePrefix" value="ROLE_"/>
            <property name="searchSubtree" value="true"/>
            <property name="convertToUpperCase" value="true"/>
            <property name="groupRoleAttribute" value="${ldap.group_role_attribute}"/>
        </bean>
    </constructor-arg>
</bean>

有可能实现这样的目标吗? 如果是,您能帮我解决这个问题吗?

非常感谢 !

首先,您需要定义您的自定义过滤器

package com.example;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import javax.servlet.*;
import java.io.IOException;

public class CustomAuthFilter implements Filter {


    private AuthenticationManager authenticationManager;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        String username = servletRequest.getParameter("username");
        String password = servletRequest.getParameter("password");
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
        Authentication successfulAuthentication;
        try {
            successfulAuthentication = authenticationManager.authenticate(authRequest);
        } catch (Exception exception) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        SecurityContextHolder.getContext().setAuthentication(successfulAuthentication);
        filterChain.doFilter(servletRequest, servletResponse);

    }

    @Override
    public void destroy() {

    }

    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }
}

将此过滤器定义为spring bean

<bean id="customFilter" class="com.example.CustomAuthFilter">
    <property name="authenticationManager" ref="authenticationManager" />
<bean>

将此过滤器添加到Spring Security过滤器链

<security:http ...>
    <custom-filter ref="customFilter" position="PRE_AUTH_FILTER" />
</security:http>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM