ProviderNotFoundException:未找到 ExpiringUsernameAuthenticationToken 的 AuthenticationProvider
ProviderNotFoundException: No AuthenticationProvider found for ExpiringUsernameAuthenticationToken
我们使用 Spring 安全和 Spring SAML 开发了一个应用程序,它在我们使用 SSOCircle 作为 IDP 的开发环境中运行。当我们使用他们的 IDP 进入客户的环境时,只要我们不暂停,我们就能够毫无问题地通过应用程序进行身份验证和导航。如果用户在提交之前在页面上暂停超过一分钟,应用程序将重定向到原始登录页面并且提交的数据将丢失。
日志显示:
o.s.s.w.a.ExceptionTranslationFilter
- Authentication exception occurred; redirecting to authentication entry point
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.providers.ExpiringUsernameAuthenticationToken
在此之前,您的日志大约每分钟都会显示类似于以下内容的内容:
SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.providers.ExpiringUsernameAuthenticationToken@e6313ceb: Principal: REDACTED
客户告诉我们,他们的 IDP 超时为 60 秒,偏差时间为 +-30 秒。
我们要求他们暂时将 IDP 超时调整为 30 分钟,然后我们的问题就解决了。当我们投入生产时,我们必须有 60 秒的原始设置。
我们的应用程序正在使用 SAMLAuthenticationProvider:
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(samlAuthenticationProvider());
}
@Bean
public SAMLAuthenticationProvider samlAuthenticationProvider() {
SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
samlAuthenticationProvider.setForcePrincipalAsString(false);
samlAuthenticationProvider.setUserDetails(samlUserDetailsService);
return samlAuthenticationProvider;
}
我们如何配置 ExpiringUsernameAuthenticationToken 来使用它?如果未设置原始身份验证,为什么会起作用?
为什么应用程序在 IDP 会话过期时尝试重新验证?
WebSSOProfileConsumerImpl 和 SingleLogoutProfileImpl 都提供了设置 responseSkew 的方法。应将其设置为等于、小于还是大于 IDP 的延迟时间?
Spring SAML 默认遵守 IDP 在其 SAML 响应中提供的 SessionNotOnOrAfter
字段。该字段表示一旦时间达到提供的值,用户必须重新进行身份验证。
Spring SAML 尝试通过将当前 Authentication
对象发送到 AuthenticationManager
来重新验证用户,后者会尝试找到支持 [=14= 的 AuhenticationProvier
] 这种类型的对象(ExpiringUsernameAuthenticationToken
在 Spring SAML 的情况下)。在您的情况下,没有这样的提供者 - 这就是您看到 ProviderNotFoundException
异常的原因。发生此错误后 Spring 安全性可能会调用默认值 EntryPoint
,它将您的用户重定向到登录页面。
为了忽略 SessionNotOnOrAfter
值,只需扩展 class SAMLAuthenticationProvider
,覆盖方法 getExpirationDate
并使其成为 return null
。然后在 securityContext.xml
.
中使用新的 class
但正确的解决方案是让您的 IDP return SessionNotOnOrAfter
值具有合理的会话长度 - 我想知道他们为什么坚持在那里使用 60 秒。
我们使用 Spring 安全和 Spring SAML 开发了一个应用程序,它在我们使用 SSOCircle 作为 IDP 的开发环境中运行。当我们使用他们的 IDP 进入客户的环境时,只要我们不暂停,我们就能够毫无问题地通过应用程序进行身份验证和导航。如果用户在提交之前在页面上暂停超过一分钟,应用程序将重定向到原始登录页面并且提交的数据将丢失。
日志显示:
o.s.s.w.a.ExceptionTranslationFilter
- Authentication exception occurred; redirecting to authentication entry point
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.providers.ExpiringUsernameAuthenticationToken
在此之前,您的日志大约每分钟都会显示类似于以下内容的内容:
SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.providers.ExpiringUsernameAuthenticationToken@e6313ceb: Principal: REDACTED
客户告诉我们,他们的 IDP 超时为 60 秒,偏差时间为 +-30 秒。
我们要求他们暂时将 IDP 超时调整为 30 分钟,然后我们的问题就解决了。当我们投入生产时,我们必须有 60 秒的原始设置。
我们的应用程序正在使用 SAMLAuthenticationProvider:
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(samlAuthenticationProvider());
}
@Bean
public SAMLAuthenticationProvider samlAuthenticationProvider() {
SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
samlAuthenticationProvider.setForcePrincipalAsString(false);
samlAuthenticationProvider.setUserDetails(samlUserDetailsService);
return samlAuthenticationProvider;
}
我们如何配置 ExpiringUsernameAuthenticationToken 来使用它?如果未设置原始身份验证,为什么会起作用?
为什么应用程序在 IDP 会话过期时尝试重新验证?
WebSSOProfileConsumerImpl 和 SingleLogoutProfileImpl 都提供了设置 responseSkew 的方法。应将其设置为等于、小于还是大于 IDP 的延迟时间?
Spring SAML 默认遵守 IDP 在其 SAML 响应中提供的 SessionNotOnOrAfter
字段。该字段表示一旦时间达到提供的值,用户必须重新进行身份验证。
Spring SAML 尝试通过将当前 Authentication
对象发送到 AuthenticationManager
来重新验证用户,后者会尝试找到支持 [=14= 的 AuhenticationProvier
] 这种类型的对象(ExpiringUsernameAuthenticationToken
在 Spring SAML 的情况下)。在您的情况下,没有这样的提供者 - 这就是您看到 ProviderNotFoundException
异常的原因。发生此错误后 Spring 安全性可能会调用默认值 EntryPoint
,它将您的用户重定向到登录页面。
为了忽略 SessionNotOnOrAfter
值,只需扩展 class SAMLAuthenticationProvider
,覆盖方法 getExpirationDate
并使其成为 return null
。然后在 securityContext.xml
.
但正确的解决方案是让您的 IDP return SessionNotOnOrAfter
值具有合理的会话长度 - 我想知道他们为什么坚持在那里使用 60 秒。