我已经完成了整个模拟设置:过滤器、身份验证、工作。这是一个基于SpringBoot的Vaadin应用程序。
@Bean
public SwitchUserFilter switchUserFilter() {
SwitchUserFilter filter = new SwitchUserFilter();
filter.setUserDetailsService(userDetailsService);
filter.setSwitchUserMatcher(new AntPathRequestMatcher("/impersonate", "GET"));
filter.setExitUserUrl("/impersonate/logout");
filter.setTargetUrl("/");
return filter;
}
据我了解,管理员定期登录后,手动输入的模拟 URL 应该可以正确进行模拟。但当然不是。
我看到执行进入 SwitchUserFilter,URL 匹配,并且它尝试进行模拟(createSwitchUserToken)。但是Spring的ThreadLocalSecurityContextHolderStrategy认为当前没有用户登录,因为它的contextHolder包含null。然后用 EmptyContext 填充,并且由于空检查,用户切换在 SwitchUserGrantedAuthority 中失败。
为什么上下文为空?
听起来问题可能与在模拟尝试之前未正确填充安全上下文有关。
您可以尝试以下任一方法来解决该问题吗:
安全上下文是否已正确填充? 在尝试模拟之前,请确保已使用经过身份验证的用户正确填充安全上下文。为了确保相同,请检查身份验证过程是否正确设置安全上下文。
验证安全过滤器的顺序 - 安全过滤器的顺序至关重要。请确保 SwitchUserFilter 放置在过滤器链中身份验证过滤器之后。
检查您的自定义安全配置 - 确保您的安全配置已正确设置以允许模拟。
这是第 3 点的示例配置:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.switchuser.SwitchUserFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/impersonate", "/impersonate/logout").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.permitAll()
.and()
.addFilterAfter(switchUserFilter(), SwitchUserFilter.class);
}
@Bean
public SwitchUserFilter switchUserFilter() {
SwitchUserFilter filter = new SwitchUserFilter();
filter.setUserDetailsService(userDetailsService);
filter.setSwitchUserMatcher(new AntPathRequestMatcher("/impersonate", "GET"));
filter.setExitUserUrl("/impersonate/logout");
filter.setTargetUrl("/");
return filter;
}
}
尝试调试上下文 - 您还应该尝试调试安全上下文,而不是调试过滤器。添加一些日志或断点来检查模拟尝试前后的安全上下文状态。
确保身份验证正常工作 - 在尝试模拟之前验证管理员用户是否经过正确身份验证并且安全上下文包含正确的身份验证对象。
交叉验证您的 Spring Security 版本,以防上述方法不起作用 - 确保您使用的是支持 SwitchUserFilter 的 Spring Security 兼容版本。
谢谢!如果它适合您,请通知我:)