如何有条件地跳过Grails Spring Security插件过滤器链

时间:2015-05-10 00:50:52

标签: grails spring-security grails-plugin

我有一个独特的场景我试图在Spring Security插件的限制下解决(版本1.2.7.3,如果是好的)。我创建了一个自定义SSO插件,允许使用签名URL登录。自定义插件工作得很好,我根据文档添加了在resources.groovy中创建bean并添加到BootStrap.groovy中的过滤器链中。

SpringSecurityUtils.clientRegisterFilter('ssoFilter', SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)

一旦用户登录,一切运行良好,并且添加到安全上下文的现有活动会话将对用户进行身份验证。

我有一个用例,在这个用例中,已经过身份验证的用户可能会在SSO请求中与不同的用户返回同一浏览器(即同一会话cookie)。我想让过滤器链注意到URL的查询字符串中的'sso = true'。

我现在看到的行为是从未到达SSO,因为原始用户已经被安全上下文验证。我无法在SecurityContextPersistenceFilter之前添加SSO过滤器,因为这会导致SSO过滤器不断被命中并且实际上没有实际呈现的问题。这是在文档之后,我看到它说你不应该在安全上下文过滤器之前放置任何过滤器。

我已经考虑过专门为具有'sso = true'的网址创建一个特殊的过滤器链(我在未经身份验证的流程中通过向{{{{{}}添加自定义RequestMatcherAuthenticationEntryPoint实现来执行此操作3}})使用springsecurity.filterChain.chainMap配置说。但是,从文档和实验中可以看出,只过滤了路径。

有没有办法确保在URL上看到'sso = true'时,SSO过滤器在仍具有安全上下文可用性的情况下被命中,或者SecurityContextPersistenceFilter可以将请求传递给SSO过滤器?

2 个答案:

答案 0 :(得分:5)

在我看来,您可以使用自定义SecurityContextRepository

Spring Security Grails插件的

Version 1.2.7.3似乎使用了Spring Security 3.0.7。正如Section 8.3.1 of the Spring Security reference中提到的,从Spring Security 3.0开始,SecurityContextPersistenceFilter配置了SecurityContextRepository bean,负责加载和保存SecurityContext。默认情况下,这是HttpSessionSecurityContextRepository的实例。

您可以创建一个扩展HttpSessionSecurityContextRepository的自定义类。如果请求包含sso=true查询参数,则自定义子类可以覆盖loadContext(HttpRequestResponseHolder)方法以删除“SPRING_SECURITY_CONTEXT”会话属性。

您可以在GitHub上查看Spring Security 3.0.7中HttpSessionSecurityContextRepository的实现:
https://github.com/spring-projects/spring-security/blob/3.0.7.RELEASE/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java

相关:How can I use Spring Security without sessions?

答案 1 :(得分:1)

丹尼尔, 您的解决方案有效 这是我的片段

@Override
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
    logger.debug("loadContext entry");
    String ssoParameter = requestResponseHolder.getRequest().getParameter("sso");

    if (ssoParameter != null && ssoParameter.equalsIgnoreCase("true")) {
        HttpSession session = requestResponseHolder.getRequest().getSession(false);
        if (session != null) session.invalidate();
    }
    return super.loadContext(requestResponseHolder);
}