使用Spring Security实现SingleSign。
在使用spring security替换基于cookie的身份验证后,我们遇到了一个奇怪的情况。
在securityContext.xml中添加SAMLContextProviderImpl,我看到请求无限重定向,即上下文被多次附加。
bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>
因此我用
代替了它 <bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderLB">
<property name="scheme" value="https"/>
<property name="serverName" value="ServerName"/>
<property name="serverPort" value="43"/>
<property name="includeServerPortInRequestURL" value="false"/>
<property name="contextPath" value="/appcontext"/>
</bean>
使用反向代理添加ContextProvider后,我没有看到多重定向。正确加载上下文。但是在chrome和firefox中我看到应用程序没有正确加载,从开发人员工具我看到错误: 混合内容:&#39; https://xportal/tools&#39;是通过HTTPS加载的,但请求了不安全的表单操作&#39; http://xportal/tools&#39;。此请求已被阻止;内容必须通过HTTPS提供。
如果我们刷新页面,应用程序加载正常。但它仅在第一时间被阻止。
对此有任何帮助将不胜感激。
答案 0 :(得分:1)
我在谷歌搜索期间遇到了您的问题,因为我遇到了同样的问题。发生这种情况的原因是因为SAMLContextProviderLB完成了部分工作,但它没有涵盖您的应用程序位于iframe内的情况。
在这种情况下会发生的情况是,受spring spring saml保护的原始请求URL存储在用户的会话中(假设您正在使用SavedRequestAwareAuthenticationSuccessHandler)。现在,因为您的应用程序正在负载平衡器后面运行,可能是处理ssl卸载,您的应用程序实际上将URL视为普通的http,这是存储的内容。
在idp成功执行后,断言将发布到/ saml / SSO / alias / {sp-entity-id}的acs url。这是SAMLContextProviderLB发挥作用的地方,它可以很好地处理它。
然后Spring安全性(通过SavedRequestAwareAuthenticationSuccessHandler)将检索先前存储在会话中的原始请求URL,并将重定向到该位置。这是问题发生的地方。它将url存储为普通的http,因为这是应用程序看到请求的方式,因为它位于负载均衡器的后面。
就chrome而言,它见证了一些非https活动,因此没有办法。
因此,解决方案是执行与SAMLContextProviderLB相同的操作 - 基本上只需在URL中将http重写为https。遗憾的是,由于requestCache变量是私有的,因此无法简单地扩展SavedRequestAwareAuthenticationSuccessHandler。而只是复制并粘贴这个类 - 我刚刚添加了一行来用https替换http。
package com.blah;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.util.StringUtils;
public class SavedRequestAwareAuthenticationSuccessHandlerLB extends SimpleUrlAuthenticationSuccessHandler {
protected final Log logger = LogFactory.getLog(this.getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {
SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest == null) {
super.onAuthenticationSuccess(request, response, authentication);
return;
}
String targetUrlParameter = getTargetUrlParameter();
if (isAlwaysUseDefaultTargetUrl()
|| (targetUrlParameter != null && StringUtils.hasText(request
.getParameter(targetUrlParameter)))) {
requestCache.removeRequest(request, response);
super.onAuthenticationSuccess(request, response, authentication);
return;
}
clearAuthenticationAttributes(request);
// Use the DefaultSavedRequest URL
String targetUrl = savedRequest.getRedirectUrl();
targetUrl = StringUtils.replace(targetUrl, "http://", "https://");
logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
}
希望有所帮助。