【发布时间】:2015-01-12 08:06:12
【问题描述】:
我有一个带有依赖项的 oauth2 客户端 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
关于为什么重定向循环的任何想法?先感谢您。
[日志 sn-p]https://gist.github.com/yterradas/61da3f6eccc683b3a086
以下是安全配置。
@配置
公共类 SecurityConfig {
@配置
@EnableWebMvcSecurity
受保护的静态类 WebSecurityConfig 扩展 WebSecurityConfigurerAdapter {
@自动连线
私人 OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationProcessingFilter;
@自动连线
私人 LoginUrlAuthenticationEntryPoint vaultAuthenticationEntryPoint;
@SuppressWarnings({"SpringJavaAutowiringInspection"})
@自动连线
私人 OAuth2ClientContextFilter oAuth2ClientContextFilter;
@覆盖
受保护的无效配置(HttpSecurity http)抛出异常{
// @格式化程序:关闭
http
.authorizeRequests()
.antMatchers("/**").authenticated()
。和()
.exceptionHandling().authenticationEntryPoint(vaultAuthenticationEntryPoint)
。和()
.addFilterAfter(oAuth2ClientContextFilter, ExceptionTranslationFilter.class)
.addFilterBefore(oAuth2ClientAuthenticationProcessingFilter, FilterSecurityInterceptor.class)
.anonymous().disable();
// @格式化程序:打开
}
@覆盖
公共无效配置(WebSecurity web)抛出异常{
// @格式化程序:关闭
网络
/* 去做:
在生产中禁用调试
*/
.调试(真);
// @格式化程序:开启
}
}
@配置
@EnableOAuth2Client
受保护的静态类 ClientSecurityConfig {
@Value("${app.name}") 私有字符串 appId;
@Value("${app.clientId}") 私有字符串 appClientId;
@Value("${app.clientSecret}") 私有字符串 appClientSecret;
@Value("${app.redirectUrl}") 私有字符串 appRedirectUrl;
@Value("${vault.accessTokenUrl}") 私有字符串 vaultAccessTokenUrl;
@Value("${vault.userAuthorizationUrl}") 私有字符串 vaultUserAuthorizationUrl;
@Value("${vault.checkTokenUrl}") 私有字符串 vaultCheckTokenUrl;
@SuppressWarnings({"SpringJavaAutowiringInspection"})
@资源
@Qualifier("oauth2ClientContext")
私人 OAuth2ClientContext oAuth2ClientContext;
@自动连线
@Qualifier("安全数据源")
私有数据源安全数据源;
@自动连线
私有 MappingJackson2HttpMessageConverter jackson2HttpMessageConverter;
@豆角,扁豆
公共 OAuth2RestOperations oAuth2RestOperations() {
AccessTokenProviderChain 提供者 = 新的 AccessTokenProviderChain(
Arrays.asList(新 AuthorizationCodeAccessTokenProvider())
);
provider.setClientTokenServices(new JdbcClientTokenServices(securityDataSource));
OAuth2RestTemplate 模板 = 新 OAuth2RestTemplate(oAuth2Resource(), oAuth2ClientContext);
模板.setAccessTokenProvider(提供者);
template.setMessageConverters(Arrays.asList(jackson2HttpMessageConverter));
返回模板;
}
@豆角,扁豆
OAuth2ProtectedResourceDetails oAuth2Resource() {
AuthorizationCodeResourceDetails 资源 = new AuthorizationCodeResourceDetails();
资源.setId(appId);
resource.setAuthenticationScheme(AuthenticationScheme.query);
resource.setAccessTokenUri(vaultAccessTokenUrl);
resource.setUserAuthorizationUri(vaultUserAuthorizationUrl);
resource.setUseCurrentUri(false);
resource.setPreEstablishedRedirectUri(appRedirectUrl);
资源.setClientId(appClientId);
资源.setClientSecret(appClientSecret);
resource.setClientAuthenticationScheme(AuthenticationScheme.form);
返回资源;
}
@豆角,扁豆
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);
返回令牌服务;
}
@豆角,扁豆
LoginUrlAuthenticationEntryPoint oAuth2AuthenticationEntryPoint() {
return new LoginUrlAuthenticationEntryPoint("/vaultLogin");
}
@豆角,扁豆
OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationProcessingFilter() {
OAuth2ClientAuthenticationProcessingFilter 过滤器 =
新的 OAuth2ClientAuthenticationProcessingFilter("/vaultLogin");
filter.setRestTemplate(oAuth2RestOperations());
filter.setTokenServices(oAuth2RemoteTokenServices());
返回过滤器;
}
}
}
【问题讨论】:
-
授权服务器在哪里。它的检查令牌端点是否可用(你可以卷曲它)吗?
-
授权服务器是一个单独的组件,不在同一个项目中。是的,我可以卷曲它。我可以看到正在创建授权,以及已启动对已保存请求的重定向。我不确定,但我认为上下文没有被保存。之所以这么想是因为执行前后的Context都有null认证。
-
我特别询问您是否可以卷曲 /check_token 端点。它不是规范的一部分,因此取决于实现,它可能存在也可能不存在(您的客户似乎正在尝试使用它)。
-
@DaveSyer 是的,我可以卷曲它。另外,我有一个自定义的
RemoteTokenServices来处理验证,因为授权服务器不使用 http-basic 进行验证。我已经用日志 sn-p 更新了这个问题。也许这会有所帮助。
标签: spring-security spring-boot spring-security-oauth2