【发布时间】: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 不适用于基本身份验证。
会发生这样的事情:
-
当调用 /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; 所以在 SecurityContext 中你有关于 xyz 用户的信息。
然后,当它重定向到目标 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;
- 如您所见,它检查
existingAuth.getName().equals(username)),在本例中为xyz。但是登录的用户不同,因此过滤器再次对用户进行身份验证,并且 SwitchUserFilter 完成的所有工作都将被覆盖。
他们有什么办法解决这个问题吗?我可以覆盖BasicAuthenticationFilter吗?
【问题讨论】:
标签: java spring spring-security