【问题标题】:SwitchUserFilter not working in Spring security when used with Basic Authentication与基本身份验证一起使用时,SwitchUserFilter 在 Spring 安全性中不起作用
【发布时间】:2015-02-03 14:20:59
【问题描述】:

我在 Spring 安全性中遇到了 SwitchUserFilter 问题。我有以下配置:

<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg name="searchBase" value=""/>
    <constructor-arg name="searchFilter" value="(uid={0})"/>
    <constructor-arg name="contextSource" ref="ldapContext"/>
</bean>

<security:ldap-server id="ldapContext" url="ldap://xxxxxxx"/>

<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <constructor-arg name="authenticator">
        <bean
            class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <constructor-arg ref="ldapContext" />
            <property name="userSearch" ref="ldapUserSearch" />
        </bean>
    </constructor-arg>
    <constructor-arg name="authoritiesPopulator" ref="dbLDAPAuthPopulator" />
</bean>
<security:authentication-manager>
    <security:authentication-provider ref="ldapAuthProvider"/>
</security:authentication-manager>

并且对应的 SwitchUserFilter bean 被创建为:

SwitchUserFilter switchUserFilter = new SwitchUserFilter();
switchUserFilter.setUserDetailsService(ldapUserDetailsService);
switchUserFilter.setTargetUrl("/");
switchUserFilter.setSwitchUserUrl("/impersonate");
switchUserFilter.setUsernameParameter("username");
switchUserFilter.setExitUserUrl("/unimpersonate");

当我转到 URL“/impersonate”时,用户会被正确模拟。但是,当重定向发送到目标 url 即“/”时,用户再次使用基本身份验证进行身份验证。

我查看了 SwitchUserFilter 和 BasicAuthenticationFilter 的代码,似乎 SU 不适用于基本身份验证。

会发生这样的事情:

  1. 当调用 /impersonate?username=xyz url 时,它会转到 SwitchUserFilter,从 ldap 获取 xyz 用户的详细信息,然后在会话中设置安全上下文。代码sn-p如下:

    if (requiresSwitchUser(request)) { // 如果设置,尝试切换并存储原始 尝试 { 认证 targetUser = attemptSwitchUser(request);

            // update the current context to the new target user
            SecurityContextHolder.getContext().setAuthentication(targetUser);
    
            // redirect to target url
            successHandler.onAuthenticationSuccess(request, response, targetUser);
        } catch (AuthenticationException e) {
            logger.debug("Switch User failed", e);
            failureHandler.onAuthenticationFailure(request, response, e);
        }
    
        return;
    
  2. 所以在 SecurityContext 中你有关于 xyz 用户的信息。

  3. 然后,当它重定向到目标 url 时,即调用“/”basicAuthenticationFilter 来检查用户是否经过身份验证。代码sn-p:

Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();

    if(existingAuth == null || !existingAuth.isAuthenticated()) {
        return true;
    }

    // Limit username comparison to providers which use usernames (ie UsernamePasswordAuthenticationToken)
    // (see SEC-348)

    if (existingAuth instanceof UsernamePasswordAuthenticationToken && !existingAuth.getName().equals(username)) {
        return true;
    }

    // Handle unusual condition where an AnonymousAuthenticationToken is already present
    // This shouldn't happen very often, as BasicProcessingFitler is meant to be earlier in the filter
    // chain than AnonymousAuthenticationFilter. Nevertheless, presence of both an AnonymousAuthenticationToken
    // together with a BASIC authentication request header should indicate reauthentication using the
    // BASIC protocol is desirable. This behaviour is also consistent with that provided by form and digest,
    // both of which force re-authentication if the respective header is detected (and in doing so replace
    // any existing AnonymousAuthenticationToken). See SEC-610.
    if (existingAuth instanceof AnonymousAuthenticationToken) {
        return true;
    }

    return false;
  1. 如您所见,它检查existingAuth.getName().equals(username)),在本例中为xyz。但是登录的用户不同,因此过滤器再次对用户进行身份验证,并且 SwitchUserFilter 完成的所有工作都将被覆盖。

他们有什么办法解决这个问题吗?我可以覆盖BasicAuthenticationFilter吗?

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    这个问题已经很老了,但是如果有人遇到它,答案在今天仍然有效。您没有为 Spring Security 显示您的 &lt;http /&gt; 节,但您需要确保通过模拟授予的角色与绕过 /* 的身份验证所需的角色(authority)相同。如果不是,则系统会要求您进行身份验证。

    您可以通过实现SwitchUserAuthorityChanger 的扩展并将其引用传递给SwitchUserFilter 来指定要在模拟时授予的自定义权限。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-08
      • 1970-01-01
      • 2014-09-06
      • 2014-01-22
      • 2016-01-11
      • 2020-02-09
      • 1970-01-01
      相关资源
      最近更新 更多