响应的 InResponseToField 与发送的消息不对应:SAML 错误 SpringSecurity - 4.2.13-RELEASE
InResponseToField of the Response doesn't correspond to sent message: SAML error SpringSecurity - 4.2.13-RELEASE
我的 Web 应用程序部署在 Amazon ECS 上并使用 ALB 并从堡垒主机访问该应用程序。我正在使用 Okta 进行 SSO。登录页面成功重定向到 Okta,当请求返回应用程序服务器时进行身份验证后,出现以下错误 -
Caused by: org.opensaml.common.SAMLException: InResponseToField of the Response doesn't correspond to sent message a491gda80cgh3a2b5bb3j8ebd515d2
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:139)
我正在使用 CustomSAMLContextProvider 并按照其他答案中的建议将 MessageStorageFactory 设置为 EmptyStorageFactory。
我不确定为什么这个检查还在进行。
这是我的自定义 SAMLContextProviderImpl class -
public class SAMLMultipleEndpointContextProvider extends SAMLContextProviderImpl {
/**
* Creates a SAMLContext with local entity values filled. LocalEntityId is set to server name of the request. Also
* request and response must be stored in the context as message transports.
*
* @param request request
* @param response response
* @return context
* @throws MetadataProviderException in case of metadata problems
*/
@Override
public SAMLMessageContext getLocalEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {
SAMLMessageContext context = new SAMLMessageContext();
populateGenericContext(request, response, context);
populateLocalEntityId(context, request.getServerName());
populateLocalContext(context);
return context;
}
/**
* Creates a SAMLContext with local entity and peer values filled. LocalEntityId is set to server name of the
* request. Also request and response must be stored in the context as message transports. Should be used when both
* local entity and peer entity can be determined from the request.
*
* @param request request
* @param response response
* @return context
* @throws MetadataProviderException in case of metadata problems
*/
@Override
public SAMLMessageContext getLocalAndPeerEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {
SAMLMessageContext context = new SAMLMessageContext();
populateGenericContext(request, response, context);
populateLocalEntityId(context, request.getServerName());
populateLocalContext(context);
populatePeerEntityId(context);
populatePeerContext(context);
return context;
}
/**
* Populate LocalEntityId with retrieved entityId from metadata manager using given localAlias parameter value.
*/
@Override
public void populateLocalEntityId(SAMLMessageContext context, String localAlias) throws MetadataProviderException {
String entityId = metadata.getEntityIdForAlias(localAlias);
QName localEntityRole = SPSSODescriptor.DEFAULT_ELEMENT_NAME;
if (entityId == null) {
throw new MetadataProviderException("No local entity found for alias " + localAlias + ", verify your configuration.");
} else {
logger.debug("Using SP {} specified in request with alias {}", entityId, localAlias);
}
context.setLocalEntityId(entityId);
context.setLocalEntityRole(localEntityRole);
}
/**
* Disable the check for InResponseToField from SSO message response.
*/
@Override
public void setStorageFactory(SAMLMessageStorageFactory storageFactory) {
super.setStorageFactory(new EmptyStorageFactory());
}
}
为了遵守 SAML 规范中定义的规则,必须针对 SP-initiated SSO 流程中的 SAML AuthNRequest 验证 SAML 响应。 默认情况下 Spring SAML 将 SAML AuthNRequest 存储在内存中,因此包含 SAML 响应作为有效负载的 HTTP POST 请求必须命中创建 AuthNRequest 的同一 JVM .如果LB不能保证粘性,那么你需要实现一个消息存储(org.springframework.security.saml.storage.SAMLMessageStorage
,org.springframework.security.saml.storage.SAMLMessageStorageFactory
),可以将消息共享给多个实例。确保在消费后从存储中删除消息以规避重播攻击,因为 SAML 共鸣是针对 one-time-usage.
我的 Web 应用程序部署在 Amazon ECS 上并使用 ALB 并从堡垒主机访问该应用程序。我正在使用 Okta 进行 SSO。登录页面成功重定向到 Okta,当请求返回应用程序服务器时进行身份验证后,出现以下错误 -
Caused by: org.opensaml.common.SAMLException: InResponseToField of the Response doesn't correspond to sent message a491gda80cgh3a2b5bb3j8ebd515d2
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:139)
我正在使用 CustomSAMLContextProvider 并按照其他答案中的建议将 MessageStorageFactory 设置为 EmptyStorageFactory。 我不确定为什么这个检查还在进行。
这是我的自定义 SAMLContextProviderImpl class -
public class SAMLMultipleEndpointContextProvider extends SAMLContextProviderImpl {
/**
* Creates a SAMLContext with local entity values filled. LocalEntityId is set to server name of the request. Also
* request and response must be stored in the context as message transports.
*
* @param request request
* @param response response
* @return context
* @throws MetadataProviderException in case of metadata problems
*/
@Override
public SAMLMessageContext getLocalEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {
SAMLMessageContext context = new SAMLMessageContext();
populateGenericContext(request, response, context);
populateLocalEntityId(context, request.getServerName());
populateLocalContext(context);
return context;
}
/**
* Creates a SAMLContext with local entity and peer values filled. LocalEntityId is set to server name of the
* request. Also request and response must be stored in the context as message transports. Should be used when both
* local entity and peer entity can be determined from the request.
*
* @param request request
* @param response response
* @return context
* @throws MetadataProviderException in case of metadata problems
*/
@Override
public SAMLMessageContext getLocalAndPeerEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {
SAMLMessageContext context = new SAMLMessageContext();
populateGenericContext(request, response, context);
populateLocalEntityId(context, request.getServerName());
populateLocalContext(context);
populatePeerEntityId(context);
populatePeerContext(context);
return context;
}
/**
* Populate LocalEntityId with retrieved entityId from metadata manager using given localAlias parameter value.
*/
@Override
public void populateLocalEntityId(SAMLMessageContext context, String localAlias) throws MetadataProviderException {
String entityId = metadata.getEntityIdForAlias(localAlias);
QName localEntityRole = SPSSODescriptor.DEFAULT_ELEMENT_NAME;
if (entityId == null) {
throw new MetadataProviderException("No local entity found for alias " + localAlias + ", verify your configuration.");
} else {
logger.debug("Using SP {} specified in request with alias {}", entityId, localAlias);
}
context.setLocalEntityId(entityId);
context.setLocalEntityRole(localEntityRole);
}
/**
* Disable the check for InResponseToField from SSO message response.
*/
@Override
public void setStorageFactory(SAMLMessageStorageFactory storageFactory) {
super.setStorageFactory(new EmptyStorageFactory());
}
}
为了遵守 SAML 规范中定义的规则,必须针对 SP-initiated SSO 流程中的 SAML AuthNRequest 验证 SAML 响应。 默认情况下 Spring SAML 将 SAML AuthNRequest 存储在内存中,因此包含 SAML 响应作为有效负载的 HTTP POST 请求必须命中创建 AuthNRequest 的同一 JVM .如果LB不能保证粘性,那么你需要实现一个消息存储(org.springframework.security.saml.storage.SAMLMessageStorage
,org.springframework.security.saml.storage.SAMLMessageStorageFactory
),可以将消息共享给多个实例。确保在消费后从存储中删除消息以规避重播攻击,因为 SAML 共鸣是针对 one-time-usage.