我有一个带依赖关系的oauth2客户端spring-boot应用程序: - spring-boot 1.2.0.RC1 - spring-security-oauth2 2.0.4.RELEASE - spring-security 3.2.5.RELEASE
客户端进行身份验证,身份验证在SecurityContextHolder中设置,但是当请求重定向到原始URL时,过滤器链会再次开始处理。我注意到在SecurityContextPersistenceFilter
contextBeforeChainExecution和contextAfterChainExecution都有一个空认证。
我基于[1] Spring Security OAuth2 (google) web app in redirect loop
的一些代码关于为什么重定向循环的任何想法?先感谢您。
[Logs snippet] https://gist.github.com/yterradas/61da3f6eccc683b3a086
以下是安全配置。
@Configuration public class SecurityConfig { @Configuration @EnableWebMvcSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationProcessingFilter; @Autowired private LoginUrlAuthenticationEntryPoint vaultAuthenticationEntryPoint; @SuppressWarnings({"SpringJavaAutowiringInspection"}) @Autowired private OAuth2ClientContextFilter oAuth2ClientContextFilter; @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests() .antMatchers("/**").authenticated() .and() .exceptionHandling().authenticationEntryPoint(vaultAuthenticationEntryPoint) .and() .addFilterAfter(oAuth2ClientContextFilter, ExceptionTranslationFilter.class) .addFilterBefore(oAuth2ClientAuthenticationProcessingFilter, FilterSecurityInterceptor.class) .anonymous().disable(); // @formatter:on } @Override public void configure(WebSecurity web) throws Exception { // @formatter:off web /* TODO: disable debug in production */ .debug(true); // @formatter:on } } @Configuration @EnableOAuth2Client protected static class ClientSecurityConfig { @Value("${app.name}") private String appId; @Value("${app.clientId}") private String appClientId; @Value("${app.clientSecret}") private String appClientSecret; @Value("${app.redirectUrl}") private String appRedirectUrl; @Value("${vault.accessTokenUrl}") private String vaultAccessTokenUrl; @Value("${vault.userAuthorizationUrl}") private String vaultUserAuthorizationUrl; @Value("${vault.checkTokenUrl}") private String vaultCheckTokenUrl; @SuppressWarnings({"SpringJavaAutowiringInspection"}) @Resource @Qualifier("oauth2ClientContext") private OAuth2ClientContext oAuth2ClientContext; @Autowired @Qualifier("securityDataSource") private DataSource securityDataSource; @Autowired private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter; @Bean public OAuth2RestOperations oAuth2RestOperations() { AccessTokenProviderChain provider = new AccessTokenProviderChain( Arrays.asList(new AuthorizationCodeAccessTokenProvider()) ); provider.setClientTokenServices(new JdbcClientTokenServices(securityDataSource)); OAuth2RestTemplate template = new OAuth2RestTemplate(oAuth2Resource(), oAuth2ClientContext); template.setAccessTokenProvider(provider); template.setMessageConverters(Arrays.asList(jackson2HttpMessageConverter)); return template; } @Bean OAuth2ProtectedResourceDetails oAuth2Resource() { AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails(); resource.setId(appId); resource.setAuthenticationScheme(AuthenticationScheme.query); resource.setAccessTokenUri(vaultAccessTokenUrl); resource.setUserAuthorizationUri(vaultUserAuthorizationUrl); resource.setUseCurrentUri(false); resource.setPreEstablishedRedirectUri(appRedirectUrl); resource.setClientId(appClientId); resource.setClientSecret(appClientSecret); resource.setClientAuthenticationScheme(AuthenticationScheme.form); return resource; } @Bean ResourceServerTokenServices oAuth2RemoteTokenServices() { VaultTokenServices tokenServices = new VaultTokenServices(); RestTemplate restOperations = new RestTemplate(); restOperations.setMessageConverters(Arrays.asList(jackson2HttpMessageConverter)); tokenServices.setRestTemplate(restOperations); tokenServices.setClientId(appClientId); tokenServices.setClientSecret(appClientSecret); tokenServices.setCheckTokenEndpointUrl(vaultCheckTokenUrl); return tokenServices; } @Bean LoginUrlAuthenticationEntryPoint oAuth2AuthenticationEntryPoint() { return new LoginUrlAuthenticationEntryPoint("/vaultLogin"); } @Bean OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationProcessingFilter() { OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter("/vaultLogin"); filter.setRestTemplate(oAuth2RestOperations()); filter.setTokenServices(oAuth2RemoteTokenServices()); return filter; } } }
答案 0 :(得分:2)
我认为你有2 OAuth2ClientContextFilters
(一个是@EnableOAuth2Client
添加的,你已经手动添加了另一个到Spring Security过滤器链)。您应该能够删除添加的那个。
答案 1 :(得分:0)
我找到了一个平庸的解决方案,它需要从SecurityFilterChain中删除几乎所有的过滤器。不幸的是,我没有我工作的应用程序的工作副本。但是,通过在打破应用程序之前删除尽可能多的过滤器然后只添加必要的过滤器来复制解决方案应该很容易。如果内存为我提供服务,那么罪魁祸首就是SecurityContextPersistenceFilter或RequestCacheAwareFilter。
答案 2 :(得分:0)
对于其他可能遇到同样问题的人 - 使用Spring Security oAuth时的重定向循环。我有这个,因为我在阻止任何直接访问Internet的防火墙后面,我的Spring Boot + Security应用程序需要调用位于Internet上的IdP的userinfo端点,例如Okta,Google等您可以通过在本地运行配置中配置代理来修复它,如下所示:
-Dhttp.proxyHost=yourhttpproxy.company.com
-Dhttp.proxyPort=yourhttproxyport
-Dhttp.nonProxyHosts=”localhost|*.yourintranetdomain1.com|*.yourintranetdomain2.com|etc”
-Dhttps.proxyHost=yourhttpsproxy.company.com
-Dhttps.proxyPort=yourhttpsproxyport
-Dhttps.nonProxyHosts=”localhost|*.yourintranetdomain1.com|*.yourintranetdomain2.com|etc”
我希望这会有所帮助。