我在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");
当我转到网址“/ impersonate”时,用户会被正确模拟。但是,当重定向发送到目标URL时,即“/”,用户再次使用基本身份验证进行身份验证。
我查看了SwitchUserFilter和BasicAuthenticationFilter的代码,看来SU不能用于基本身份验证。
这就是:
当调用/ impersonate?username = xyz url时,它会转到SwitchUserFilter,它从ldap获取xyz用户的详细信息,然后在会话中设置securitycontext。代码段如下:
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
来检查用户是否经过身份验证。代码段:
身份验证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
吗?
答案 0 :(得分:1)
这个问题已经很老了,但是如果有人遇到这个问题,答案今天仍然有效。您没有显示Spring Security的<http />
节,但需要确保模拟授予的角色与绕过authority
的身份验证所需的角色(/*
)相同。如果不是,则将要求您进行身份验证。
您可以通过实现SwitchUserAuthorityChanger
的扩展名并将其引用传递给SwitchUserFilter
来指定要在模拟时授予的自定义权限。