《SpringSecurity3》第六章第三部分翻译(Session的管理和并发)博客分类:SpringSecurityJ2EEJavaSpringSecurity安全JavaSession的管理和并发SpringSecurity的一个常见配置就是检测相同的用户以不同的session登录安全系统。这被称为并发控制(concurrencycontrol),是session管理(sessionmanagement)一系列相关配置功能的一部分。严格来说,这个功能并不是高级配置,但是它会让很多新手感到迷惑,并且最好在你对SpingSecurity整体功能有所了解的基础上再掌握它。SpringSecurity的session管理能够以两种不同的方式进行配置——session固化保护(sessionfixationprotection)和并发控制。因为并发控制的功能基于session固化保护所提供的框架,我们先介绍session固化。配置sessionfixation防护如果我们使用的是security命名空间的配置方式,session固化防护已经被默认进行了配置。如果我们要指明将其配置为与默认设置一致的话,我们需要这样:Xml代码1.httpauto-config=trueuse-expressions=true2.!--...--3.session-managementsession-fixation-protection=migrateSession/4./httpSession固化防护这个功能你可能并不会在意,除非你想扮演一个恶意的用户。我们将向你展示如何模拟一个session窃取攻击,但是在此之前,有必要理解session固化是怎么回事以及怎样防止这样的攻击。理解sessionfixation攻击Session固化是恶意用户试图窃取系统中一个未认证用户的session。对攻击者来说,可以通过各种技术来获取用户session的唯一标识(例如,JSESSIONID)。如果攻击者创建了带有用户JSESSIONID的cookie或者URL参数,他就能够访问用户的session。尽管这是一个明显的问题,但是一般情况下,如果用户没有经过认证,他们就还没有输入任何敏感信息(假设站点的安全已经正确规划了)。如果用户认证后依旧使用相同的session标识符,这个问题就会比较更加重要了。如果用户在认证后还使用相同的标识符,那攻击者现在就能访问认证过用户的session,而甚至不必要知道他们的用户名和密码。【此时,你可能很不屑并认为在现实世界中这不会发生。实际上,session窃取攻击经常发生。关于这个话题,我们建议(正如在第三章那样)你花些时间阅读由OWASP组织()发布的包含重要信息的文章以及学习案例。攻击者和恶意用户是真实存在的,如果你不了解他们常用的技术及如何避免,他们会对你的用户、应用或公司造成真正的损害。】下图展现了session固化攻击是如何发生的:既然了解了攻击如何进行,接下来我们查看SpringSecurity如何防止。使用SpringSecurity防止sessionfixation攻击如果我们能够阻止用户在认证前和认证后使用相同的session,我们就能够让攻击者掌握的sessionID信息变得没有用处。SpringSecurity的session固化防护解决这个问题的方式就是在用户认证之后明确创建一个新的session并将旧的session失效。让我们看下图:我们可以看到一个新的过滤器,o.s.s.web.session.SessionManagementFilter,负责检查一个特定的用户是否为新认证的。如果用户是新认证的,一个配置的o.s.s.web.authentication.session.SessionAuthenticationStrategy将确定要怎样做。o.s.s.web.authentication.session.SessionAuthenticationStrategy将会创建一个新的session(如果用户已经拥有一个的话),并将已存在session的内容拷贝到新session中去。这看起来很简单,但是,通过上面的图表我们可以看到,它能够有效组织恶意用户在未知用户登录后重用sessionID。模拟sessionfixation攻击此时,你可能会想要看一下在模拟session固化攻击时会涉及到什么。为了实现这一点,你需要在dogstore-security.xml中配置session固化防护失效。Xml代码1.session-managementsession-fixation-protection=none/接下来,你需要打开两个浏览器。我们将会在IE中初始化session,并从那里窃取,我们的攻击者将会使用窃取到的session在Firefox中登录。我们将会使用InternetExplorerDeveloperTools(IE8中自带)以及FirefoxWebDeveloperAdd-On(第三章中已经给过URL)来查看和控制cookie。在IE中打开JBCPPets首页,然后打开开发者工具(看“工具”下拉菜单或点击F12),并在“缓存”菜单下选择“查看Cookie信息”。在合适域下(如果使用localhost将为空)找到JSESSIONID的cookie。将sessioncookie的值复制到粘贴板上,然后登录JBCPPets站点。如果你重复“查看Cookie信息”,你将会发现JSESSIONID在登录后没有变化,这将会导致很容易受到session固化攻击。在Firefox下,打开JBCPPets站点。你将会被分配一个sessioncookie,这能通过Cookie菜单的“查看Cookie信息”菜单项查看到。为了完成我们的攻击,我们点击“EditCookie”选项,并将从IE中复制到粘贴板上的JSESSIONID值粘贴进来,如下图所示:我们的session固化攻击完成了!如果此时在Firefox中重新加载页面,你将以IE中已登录用户相同的身份进入系统,并不需要你知道用户名和密码。你是否害怕恶意用户了?现在,重新使session固化防护生效然后重新尝试这个练习。你会发现,在这种情况下,JSESSIONID在用户登录后会发生变化。因为你已经了解了session固化攻击是如何发生的,这意味着减少了可信任用户陷入这种攻击的风险。干的漂亮!细心的开发人员应该会注意到有很多种窃取sessioncookie的方式,有一些如跨站脚本攻击(XSS)可能会使得session固化防护都很脆弱。请访问OWASP站点来了解更多防止这种类型攻击的信息。比较session-fixation-protection选项session-fixation-protection属性支持三种不同的选项允许你进行修改:属性值描述none使得session固化攻击失效,不会配置SessionManagementFilter(除非其它的session-management属性不是默认值)migrateSession当用户经过认证后分配一个新的session,它保证原session的所有属性移到新session中。我们将在后面的章节中讲解,通过基于bean的方式如何进行这样的配置。newSession当用户认证后,建立一个新的session,原(未认证时)session的属性不会进行移到新session中来。在大多数场景下,默认行为即migrateSession适用于在用户登录后希望保持重要信息(如点击爱好、购物车等)的站点的站点通过session的并发控制增强对用户的保护紧随session固化防护一个很自然的用户安全增强功能就是session并发控制。如前面所描述的那样,session并发控制能够确保一个用户不能同时拥有超过一个固定数量的活跃session(典型情况是一个)。要确保这个最大值的限制需要涉及到好几个组件的协作以精确跟踪用户session活动的变化。让我们配置这个功能并了解其如何工作,然后对其进行测试。配置session并发控制既然我们要了解session并发控制所要涉及的组件,那将其运行环境搭建起来可能会更有感官的了解。首先,我们需要使得ConcurrentSessionFilter生效并在dogstore-security.xml配置。Xml代码1.httpauto-config=trueuse-expressions=true2.!--...--3.session-management4.concurrency-controlmax-sessions=1/5./session-management6./http现在,我们需要在web.xml描述文件中配置中使得o.s.s.web.session.HttpSessionEventPublisher生效,这样servelt容器将会通知SpringSecuritysession生命周期的事件(通过HttpSessionEventPublisher)。Xml代码1.listener2.listener-class3.org.springframework.web.context.ContextLoaderListener4./listener-class5./listener6.listener7.listener-class8.org.springframework.security.web.session9..HttpSessionEventPublisher10./listener-class11./listener12.servlet13.servlet-namedogstore/servlet-name这两个配置完成,session的并发控制功能也就激活了。让我们看一下它内部是如何工作的,然后我们将会通过几步操作来查看它对用户的session的保护功能。理解session并发控制我们在前面提到session并发控制试图限制相同的用户以不同的session进行访问。基于我们对session窃取方式攻击的了解,我们可以发现session并发控制能够降低攻击者窃取已登录合法用户session的风险。你觉得为什么会这样呢?Session并发控制使用o.s.s.core.session.SessionRegistry来维护一个活跃HTTPsession的列表而认证过的用户与其进行关联。当session创建或过期时,注册表中会实时进行更新,基于HttpSessionEventPublisher发布的session生命周期事件来跟踪每一个认证用户的活动session的数量。SessionAuthenticationStrategy的一个扩展类即o.s.s.web.authentication.session.ConcurrentSessionControlStrategy提供方法来实现新session的跟踪以及session并发控制的实际增强功能。每次用户访问这个安全站点时,SessionManagementFilter将会比照SessionRegistry检查这个活跃的session。如果用户活跃的session不在SessionRegistry这个活跃session列表中,最近最少被使用的session将会立即过期。在修改后的session并发控制过滤器链中的第二个参与者是o.s.s.web.session.ConcurrentSessionFilter。这个过滤器能够辨认出过期的session(典型情况下,session会被servlet容器或者被ConcurrentSessionControlStrategy强制失效掉)并通知用户他的session已经失效了。既然我们已经了解了session并发控制是如何工作的,那对我们来