我正在基于Spring安全性和Spring Security SAML扩展(RC2)编写几个Web应用程序.
我有一种基本的方式来与多个服务提供者和一个身份提供者一起工作(基于spring saml docs中定义的示例).
当用户访问SP上的受保护资源时,他将被转发到IDP上的受保护资源.因此,由于用户尚未登录,因此将其重定向到登录页面(标准的spring安全性内容).登录后,将播放原始请求,并完成authNRequest / Response,并将用户重定向到原始受保护的资源.
我现在有一个要求,以确保所有服务提供者都必须在每次请求之前向身份提供者询问用户是否已登录(而不是在SP本地进行登录).
据我了解,在每次请求期间都会存储并查询本地(SP)和远程(IDP)安全上下文,如果没有有效的上下文,则将用户转发给身份提供者以进行身份验证过程.
所以我的问题是,有没有一种方法可以在SP端配置saml / spring安全性以始终“ 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),并且很可能导致应用程序的响应速度较慢.