【问题标题】:Spring security context path resolverSpring 安全上下文路径解析器
【发布时间】:2012-11-19 12:44:11
【问题描述】:

我想定义从 spring security 设置的 session cookie 的路径,以允许从 web-app 进行多次登录。例如:

http://localhost:8080/myApp/context1/login
http://localhost:8080/myApp/context2/login
http://localhost:8080/myApp/context3/login
...

这基本上可以通过覆盖LoginUrlAuthenticationEntryPointSimpleUrlAuthenticationFailureHandlerSimpleUrlAuthenticationSuccessHandlerSimpleUrlLogoutSuccessHandler来实现。但是我找不到负责设置 cookie 上下文路径的处理程序,我需要从以下位置覆盖:

/myApp

到适当的等价物:

/myApp/context1

这是必需的,以便允许并行登录这些应用程序。

Q:tomcat如何动态改变session cookie(HttpSession)的cookie路径?

【问题讨论】:

  • 恐怕您想要实现无需修改会话即可轻松完成的事情。您的问题看起来更像是授权而不是身份验证。也许您需要为每个上下文使用角色?还是访问控制列表?
  • 对于并发身份验证并允许用户拥有多个会话,配置 ConcurrentSessionFilter 并将 maximumSession 属性设置为 -1 以允许 ConcurrentSessionControlStrategy 中的无限会话是否足够?
  • @Ravi:可能,你能解决一下吗? cookie如何区分文件夹?
  • @crudolf,但是为什么需要区分cookie路径。请提供您想要达到的目标以获得更好的解决方案的要求。
  • 也许 [this thread (last answer)][1] 中说明的方法是您想要的?! [1]:serverfault.com/questions/401574/…

标签: tomcat grails spring-security


【解决方案1】:

您的应用程序容器负责向客户端发送会话 cookie。 在 Spring Security 代码中,您只会看到如下行:

HttpSession session = request.getSession();

Spring Security 源代码中没有 session-cookie-creation 逻辑。这就是为什么没有实现接口或配置属性来提供自定义路径的原因。

要指定将分配给由您的 Web 应用程序创建的任何会话 cookie 的路径,您可以输入:

<web-app>
    <session-config>
        <cookie-config>
            <path></path>
        </cookie-config>
    </session-config>
</web-app>

在您的 web.xml 描述符中。

但是,您希望在一个 Web 应用程序中拥有多个会话。 为什么不为每个用户上下文部署新的应用程序?这是最合乎逻辑的方法。

编辑: 恐怕您想要实现无需修改会话即可轻松完成的事情。您的问题看起来更像是授权而不是身份验证。也许您需要为每个上下文使用角色?还是访问控制列表?

【讨论】:

  • 回答您的问题:因为上下文的数量是动态的。
  • 所以我想创建会话的地方并不多。显然我可以通过调用HttpSession 中的一些方法来手动设置路径。是否可以为此修补 spring 安全性?
  • HttpSession中没有这种方法。恐怕你需要得到所有的饼干。查找名称为 JSESSIONID 的 cookie。克隆它。将您的上下文相关路径设置为克隆的 cookie。对于以前的 cookie 集 maxAge0(删除它)。最后将两个 cookie 添加到响应中(由于将其 maxAge 设置为 0,前者被删除)。这很脏。研究 Tomcat/你的容器文档。也许有一些供应商的方法可以做到这一点而无需肮脏的黑客攻击?
【解决方案2】:

默认bean rememberMeServices 类型为org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices 负责设置cookie

【讨论】:

  • 这也会负责创建 HttpSession 吗?
【解决方案3】:

扩展 InlineExplodedTomcatServer

package myapp

    import org.grails.plugins.tomcat.InlineExplodedTomcatServer
    import org.grails.plugins.tomcat.TomcatLoader
    import grails.util.GrailsNameUtils
    import org.apache.catalina.connector.Connector
    import org.apache.catalina.startup.Tomcat
    import org.apache.coyote.http11.Http11NioProtocol
    import org.codehaus.groovy.grails.lifecycle.ShutdownOperations
    import org.codehaus.groovy.grails.plugins.PluginManagerHolder
    import org.codehaus.groovy.grails.plugins.GrailsPluginUtils
    import static grails.build.logging.GrailsConsole.instance as CONSOLE
    import org.apache.tomcat.util.scan.StandardJarScanner
    import org.springframework.util.ReflectionUtils


    class MyappInlineExplodedTomcatServer extends InlineExplodedTomcatServer {

        MyappInlineExplodedTomcatServer(String basedir, String webXml, String contextPath, ClassLoader classLoader) {
            super(basedir, webXml, contextPath, classLoader)
            context.setSessionCookieDomain(System.getProperty('mydomain.com'))
            context.setSessionCookiePath('/mypath')     
        }

    }

扩展tomcat服务器工厂

package myapp

import grails.web.container.EmbeddableServer

import org.grails.plugins.tomcat.TomcatServerFactory

class MyappServerFactory extends TomcatServerFactory {

    EmbeddableServer createInline(String basedir, String webXml, String contextPath, ClassLoader classLoader) {             
        new MyappInlineExplodedTomcatServer(basedir, webXml, contextPath, classLoader)      
    }

}

在 events.groovy 中设置服务器工厂

eventRunAppStart = {
        System.setProperty 'grails.server.factory','myapp.MyappServerFactory'
        }
}

显然,此配置仅在使用 grails "run-app" 运行时应用,而不是在您部署在 tomcat 或其他服务器上时应用。在 tomcat 上你必须在 tomcat 配置文件中配置它

【讨论】:

  • 谢谢,但我需要让 cookie 动态化 /mypath/mypath1
【解决方案4】:

好的……这一次我想我找到了你要找的东西。看this answer

我认为你可以在 grails 中创建一个 filter

【讨论】:

    【解决方案5】:

    请参考 Spring Security 中 successfulAuthentication 的默认行为。

    更新(来自评论的指针):关于成功认证的 2 点,spring security "Invokes the configured SessionAuthenticationStrategy to handle any session-related behaviour"。因此,请尝试为您的应用程序实现自定义 SessionControlStrategy 扩展框架提供的类,看看它是否满足您的需求。
    框架提供的策略类为ConcurrentSessionControlStrategyNullAuthenticatedSessionStrategySessionFixationProtectionStrategy


    验证成功后控制cookie创建逻辑及其值:

    1) 为您的应用程序选择记住我的服务
    例如: TokenBasedRememberMeServicesPersistentTokenBasedRememberMeServices

    2) 创建一个自定义类MyAppTokenBasedRemenberMeServices 扩展所选类,例如:TokenBasedRememberMeServices

    3) 覆盖方法protected void setCookie(String[] tokens, int maxAge, HttpServletRequest request, HttpServletResponse response)。它负责创建 cookie 并将创建的 cookie 添加到响应中(这样您就可以控制任何 cookie 值,例如上下文路径值)。此方法驻留在类中:AbstractRememberMeServices

    4) 为rememberMeServices 映射新创建的自定义类

    我希望这会有所帮助!

    【讨论】:

    • 我认为第一个链接确实非常好。但是 1-4 仅对持久登录 cookie 有用(记住我的 cookie),但我需要会话 cookie。
    • @crudolf - 您想在创建会话时设置值吗?即HttpSession
    • @crudolf - 作为一种解决方法,您可以实现HttpSessionListener。这样sessionCreated(HttpSessionEvent se) 方法就会收到会话创建的通知。然后操作您的应用程序HttpSession 值。
    • 听起来不错,是否可以在这个监听器中覆盖cookie的路径?
    • @crudolf - 我已经验证了HttpSessionEvent 方法,它没有按预期工作;因为在成功认证之前已经创建了会话。所以事件没有被提出。我已经用SessionControlStrategy 信息更新了帖子。请看看是否有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 2016-11-15
    • 2019-08-22
    • 2022-01-25
    相关资源
    最近更新 更多