使用自定义AbstractAuthenticationProcessingFilter和自定义CustomAuthenticationProvider的身份验证无法正常工作

使用自定义AbstractAuthenticationProcessingFilter和自定义CustomAuthenticationProvider的身份验证无法正常工作,authentication,spring-security,authorization,saml-2.0,Authentication,Spring Security,Authorization,Saml 2.0,我们使用SpringSecurity根据来自外部应用程序的一些用户详细信息(如userid)对用户进行身份验证,并使用安全上下文持有者执行授权。我们正在使用AbstractAuthenticationProcessingFilter的自定义实现和CustomAuthenticationProvider的自定义实现,将我们自己的UserDetailsServiceImpl注入到提供程序中,用于从数据库获取用户详细信息 当单个用户尝试登录时,它工作正常,将创建身份验证对象,并将其正确设置为Secur

我们使用SpringSecurity根据来自外部应用程序的一些用户详细信息(如userid)对用户进行身份验证,并使用安全上下文持有者执行授权。我们正在使用AbstractAuthenticationProcessingFilter的自定义实现和CustomAuthenticationProvider的自定义实现,将我们自己的UserDetailsServiceImpl注入到提供程序中,用于从数据库获取用户详细信息

当单个用户尝试登录时,它工作正常,将创建身份验证对象,并将其正确设置为SecurityCOntextHolder。但是当另一个用户尝试登录时,旧的身份验证对象会被新的身份验证对象覆盖。似乎没有在每个用户登录时创建新会话

过滤器和提供程序的实现如下所示--

自定义提供程序的实现如下所示:

    public class CustomAuthenticationProvider implements AuthenticationProvider, InitializingBean {

private final static Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);

private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService = null;
/**
* 
*/
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    if (!supports(authentication.getClass())) {
        return null;
    }

    if (logger.isDebugEnabled()) {
        logger.debug("PreAuthenticated authentication request: " + authentication);
    }

    if (authentication.getPrincipal() == null) {
        logger.debug("No pre-authenticated principal found in request.");
        return null;
    }

    UserDetails ud = preAuthenticatedUserDetailsService.loadUserDetails((PreAuthenticatedAuthenticationToken)authentication);

    PreAuthenticatedAuthenticationToken result =
            new PreAuthenticatedAuthenticationToken(ud, authentication.getCredentials(), ud.getAuthorities());
    result.setDetails(authentication.getDetails());

    return result;

}

@Override
public void afterPropertiesSet() throws Exception {
    // TODO Auto-generated method stub
}

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

/**
 * @return the preAuthenticatedUserDetailsService
 */
public AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> getPreAuthenticatedUserDetailsService() {
    return preAuthenticatedUserDetailsService;
}

/**
 * @param preAuthenticatedUserDetailsService the preAuthenticatedUserDetailsService to set
 */
public void setPreAuthenticatedUserDetailsService(
        AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService) {
    this.preAuthenticatedUserDetailsService = preAuthenticatedUserDetailsService;
}
}
<security:http>
 <security:custom-filter before="SECURITY_CONTEXT_FILTER" ref="securityContextPersistenceFilter"/>
公共类CustomAuthenticationProvider实现AuthenticationProvider,InitializingBean{ 私有最终静态记录器Logger=LoggerFactory.getLogger(CustomAuthenticationProvider.class); 私有身份验证UserDetailsService预身份验证DuserDetailsService=null; /** * */ 公共身份验证(身份验证)引发AuthenticationException{ 如果(!支持(authentication.getClass())){ 返回null; } if(logger.isDebugEnabled()){ 调试(“预验证的身份验证请求:“+身份验证”); } if(authentication.getPrincipal()==null){ debug(“在请求中找不到预验证的主体”); 返回null; } UserDetails ud=PreAuthenticatedUserDetails.loadUserDetails((PreAuthenticatedAuthenticationToken)身份验证); 预验证身份验证令牌结果= 新的预验证身份验证令牌(ud,authentication.getCredentials(),ud.getAuthories()); result.setDetails(authentication.getDetails()); 返回结果; } @凌驾 public void afterPropertieSet()引发异常{ //TODO自动生成的方法存根 } @凌驾 公共布尔支持(类身份验证){ 返回PreAuthenticatedAuthenticationToken.class.isAssignableFrom(身份验证); } /** *@返回预验证的DuserDetails服务 */ 公共身份验证UserDetailsService getPreAuthenticatedUserDetailsService(){ 返回预验证的DuserDetailsService; } /** *@param preauthenticateduserdetails服务要设置的preauthenticateduserdetails服务 */ 公共无效setPreAuthenticatedUserDetailsService( AuthenticationUserDetails服务预验证数据详细信息服务){ this.preAuthenticatedUserDetailsService=preAuthenticatedUserDetailsService; } } 我们还配置了自定义身份验证成功处理程序,以便在身份验证时将用户重定向到适当的URL-

    public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

/**
 * redirect user to appropriate home page based on user role
 */
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {

    Set<GrantedAuthority> authorities = ((UserDetails)authentication.getPrincipal()).getAuthorities();
    if(CollectionUtils.isNotEmpty(authorities)){
        GrantedAuthority role = getHighestRole(authorities);
        String targetURL = getTargetURL(role);
        if (targetURL != null) {
            log.debug("Redirecting to target Url: " + targetURL);
            getRedirectStrategy().sendRedirect(request, response, targetURL);
            return;
        }
    }

    super.onAuthenticationSuccess(request, response, authentication);

}
  }
公共类CustomAuthenticationSuccessHandler扩展了SavedRequestAwareAuthenticationSuccessHandler{
/**
*根据用户角色将用户重定向到相应的主页
*/
@凌驾
AuthenticationSuccess(HttpServletRequest请求、HttpServletResponse响应、身份验证)上的公共void引发ServletException、IOException{
设置权限=((UserDetails)authentication.getPrincipal()).getAuthories();
if(收款项不为空(主管部门)){
GrantedAuthority角色=getHighestRole(权限);
字符串targetURL=getTargetURL(角色);
if(targetURL!=null){
调试(“重定向到目标Url:+targetURL”);
getRedirectStrategy().sendRedirect(请求、响应、目标URL);
返回;
}
}
super.onAuthenticationSuccess(请求、响应、身份验证);
}
}
spring安全配置文件如下所示-

    public class DefaultAuthenticationProcessingFilter extends
    AbstractAuthenticationProcessingFilter {

private final static Logger logger = LoggerFactory.getLogger(DefaultAuthenticationProcessingFilter.class);

private static final String INTERCEPTOR_PROCESS_URL = "/sso/landingpage.action";

public DefaultAuthenticationProcessingFilter() {
    super(INTERCEPTOR_PROCESS_URL);
}

public DefaultAuthenticationProcessingFilter(
        String defaultFilterProcessesUrl) {
    super(defaultFilterProcessesUrl);
    Assert.notNull(defaultFilterProcessesUrl, "Configuration error :: DefaultFilterProcessesUrl must be specified");
}


/**
 * Method to do authentication of user
 */
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
        HttpServletResponse response) throws AuthenticationException,
        IOException, ServletException {

    logger.info("Authenticating the user .....");

    Authentication authResult = null;
    try {

        String eid = request.getParameter("EID");

        if( StringUtils.isEmpty(eid)) {
             throw new PreAuthenticatedCredentialsNotFoundException("EID param not found in request.");
        }

        String credentials = "NA";
        PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(eid, credentials);
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
        authResult = getAuthenticationManager().authenticate(authRequest);
    } catch (AuthenticationException e) {
        unsuccessfulAuthentication(request, response, e);
    } 
    return authResult;
}
    }


    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            Authentication authResult) throws IOException, ServletException {

        if (logger.isDebugEnabled()) {
            logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
        }

        SecurityContextHolder.getContext().setAuthentication(authResult);

        getRememberMeServices().loginSuccess(request, response, authResult);

        // Fire event
        if (this.eventPublisher != null) {
            eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
        }

        getSuccessHandler().onAuthenticationSuccess(request, response, authResult);
 }
    }
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="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.1.xsd
                       http://www.springframework.org/schema/security
                       http://www.springframework.org/schema/security/spring-security-3.1.xsd">

 <security:http use-expressions="true" auto-config="false" pattern="/sso/*" entry-point-ref="http403ForbiddenEntryPoint" access-denied-page="/accessdenied.action" >
    <security:anonymous enabled="false"/>
    <security:custom-filter position="BASIC_AUTH_FILTER" ref="defaultBasicAuthFilter" />
    <security:expression-handler ref="expressionHandler"/>
</security:http>

<security:http use-expressions="true" auto-config="false" pattern="/rcd/associate/*" entry-point-ref="http403ForbiddenEntryPoint"  access-denied-page="/accessdenied.action">
    <security:intercept-url pattern="/saml/sso/*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <security:custom-filter position="BASIC_AUTH_FILTER" ref="defaultBasicAuthFilter" />
    <security:expression-handler ref="expressionHandler"/>
</security:http>

<bean id="http403ForbiddenEntryPoint"
    class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />


<bean id="expressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
     <property name="permissionEvaluator" ref="customPermissionEvaluator" /> 
</bean>

<bean id="defaultBasicAuthFilter"
    class="com.example.security.authentication.DefaultAuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
    <property name="AuthenticationFailureHandler" ref="failureHandler"></property>
</bean>

<bean id="authProvider"
class="com.example.security.authentication.CustomAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
        <bean id="userDetailsServiceWrapper"
            class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <property name="userDetailsService" ref="userDetailsService" />
        </bean>
    </property>
</bean>

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

<bean id="userDetailsService" class="com.example.security.authorization.UserDetailsServiceImpl" />

 <bean id="successRedirectHandler"
      class="com.example.security.authentication.CustomAuthenticationSuccessHandler">
        <property name="defaultTargetUrl" value="/user1/user1LandingPage.action"/>
     </bean>

<bean id="failureHandler"
      class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/accessdenied.action"/>
</bean>

我们还配置了web.xml

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/spring-app-context.xml <!-- ,/WEB-INF/spring/security.xml -->
    </param-value>
</context-param>

<servlet>
    <servlet-name>example-dispatcher-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Map all /example*.action requests to the example-dispatcher-servlet for handling -->
<servlet-mapping>
    <servlet-name>example-dispatcher-servlet</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>/rcd/pages/index.jsp</welcome-file>
</welcome-file-list>

<listener>
    <listener-class>com.example.HttpSessionListenerImpl</listener-class>
</listener>


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

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

org.springframework.web.context.ContextLoaderListener
上下文配置位置
/WEB-INF/spring/spring-app-context.xml
示例调度器servlet
org.springframework.web.servlet.DispatcherServlet
上下文配置位置
/WEB-INF/spring/mvc.xml
1.
示例调度器servlet
*.行动
/rcd/pages/index.jsp
com.example.HttpSessionListenerImpl
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
springSecurityFilterChain
/*
我们正在使用spring 3.1.3和spring security 3.1.3 应在每个用户登录时创建新会话,并相应地设置安全上下文。但我的情况就是这样。我在我的应用程序中检查了debuggin,发现在用户登录时没有创建新会话。也许我在什么地方错过了它。我找不到任何相关的解决方案

在这方面的任何帮助都将不胜感激


谢谢。

对不起,伙计们,虽然我当时已经解决了这个问题,但很长一段时间我都没有看这个问题-

我在元素中使用了securityContextPersistenceFilter,配置如下-

    public class CustomAuthenticationProvider implements AuthenticationProvider, InitializingBean {

private final static Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);

private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService = null;
/**
* 
*/
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    if (!supports(authentication.getClass())) {
        return null;
    }

    if (logger.isDebugEnabled()) {
        logger.debug("PreAuthenticated authentication request: " + authentication);
    }

    if (authentication.getPrincipal() == null) {
        logger.debug("No pre-authenticated principal found in request.");
        return null;
    }

    UserDetails ud = preAuthenticatedUserDetailsService.loadUserDetails((PreAuthenticatedAuthenticationToken)authentication);

    PreAuthenticatedAuthenticationToken result =
            new PreAuthenticatedAuthenticationToken(ud, authentication.getCredentials(), ud.getAuthorities());
    result.setDetails(authentication.getDetails());

    return result;

}

@Override
public void afterPropertiesSet() throws Exception {
    // TODO Auto-generated method stub
}

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

/**
 * @return the preAuthenticatedUserDetailsService
 */
public AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> getPreAuthenticatedUserDetailsService() {
    return preAuthenticatedUserDetailsService;
}

/**
 * @param preAuthenticatedUserDetailsService the preAuthenticatedUserDetailsService to set
 */
public void setPreAuthenticatedUserDetailsService(
        AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService) {
    this.preAuthenticatedUserDetailsService = preAuthenticatedUserDetailsService;
}
}
<security:http>
 <security:custom-filter before="SECURITY_CONTEXT_FILTER" ref="securityContextPersistenceFilter"/>



如何解决此问题?请添加您的答案。@Ebanath,您希望其他人帮助您,但没有共享解决方案,为什么?我有类似的要求。您能看看我的问题吗