我正在编写几个基于 spring security 和 spring security saml 扩展 (RC2) 的 Web 应用程序。
我使用单点登录以基本方式与多个服务提供商和一个身份提供商合作(基于 spring saml 文档中定义的示例)。
当用户访问SP上的 protected 资源时,他被转发到IDP上的 protected 资源。因此,因为用户尚未登录,他们将被重定向到登录页面(标准的 spring 安全性内容)。登录后,回放原始请求并完成 authNRequest/Response 并将用户重定向到原始安全资源。
我现在有一个要求,确保所有服务提供者必须在每次请求之前询问身份提供者用户是否登录(而不是在 SP 本地进行)。
据我了解,在每次请求期间都会存储和查询本地 (SP) 和远程 (IDP) 安全上下文,如果没有有效的上下文,则用户会被转发给身份提供者以通过授权过程。
所以我的问题是,有没有一种方法可以在 SP 端配置 saml/spring security 以始终“ping”或要求 IDP 检查当前用户是否已登录,或者这种事情是否不必要/不受支持.
提前致谢
最佳答案
你是对的,Spring SAML 在每个请求期间查询本地安全上下文,并在无效时将用户转发给 IDP。
定义上下文何时无效的典型机制是使用 SAML 的属性 SessionNotOnOrAfter
。该属性包含在从 IDP 发回的断言的 AuthenticationStatement 中。一旦时间超过 SessionNotOnOrAfter
中提供的值,Spring SAML 将自动重新验证用户。
如果您想对每个请求重新进行身份验证,您可以添加一个类似于此的新自定义过滤器:
package fi.test;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
public class ReAuthenticateFilter extends GenericFilterBean {
private static final String FILTER_APPLIED = "__spring_security_filterReAuthenticate_filterApplied";
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
protected void invoke(FilterInvocation fi) throws IOException, ServletException {
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)) {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} else {
if (fi.getRequest() != null) {
fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
}
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
if (authentication != null) {
authentication.setAuthenticated(false);
}
}
}
}
然后您可以在 Spring 配置中包含过滤器:
<security:http entry-point-ref="samlEntryPoint">
<security:custom-filter after="SECURITY_CONTEXT_FILTER" ref="reAuthenticateFilter"/>
...
</security:http>
<bean id="reAuthenticateFilter" class="fi.test.ReAuthenticateFilter"/>
对每个请求重新验证是相当昂贵的操作(通过用户浏览器往返 IDP)并且可能导致应用程序的响应性差。
关于java - IDP 的 Spring SAML 预授权检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24394779/