参考链接:https://xueliang.org/article/detail/20170302232815082

session 管理

Spring Security 通过 http 元素下的子元素 session-management 提供了对 Http Session 管理的支持。

检测 session 超时

Spring Security 可以在用户使用已经超时的 sessionId 进行请求时将用户引导到指定的页面。这个可以通过如下配置来实现。

   <security:http>
...
<!-- session 管理,invalid-session-url 指定使用已经超时的 sessionId 进行请求需要重定向的页面 -->
<security:session-management invalid-session-url="/session_timeout.jsp"/>
...
</security:http>

需要注意的是 session 超时的重定向页面应当是不需要认证的,否则再重定向到 session 超时页面时会直接转到用户登录页面。此外如果你使用这种方式来检测 session 超时,当你退出了登录,然后在没有关闭浏览器的情况下又重新进行了登录,Spring Security 可能会错误的报告 session 已经超时。这是因为即使你已经退出登录了,但当你设置 session 无效时,对应保存 session 信息的 cookie 并没有被清除,等下次请求时还是会使用之前的 sessionId 进行请求。解决办法是显示的定义用户在退出登录时删除对应的保存 session 信息的 cookie。

   <security:http>
...
<!-- 退出登录时删除 session 对应的 cookie -->
<security:logout delete-cookies="JSESSIONID"/>
...
</security:http>

此外,Spring Security 并不保证这对所有的 Servlet 容器都有效,到底在你的容器上有没有效,需要你自己进行实验。

concurrency-control

通常情况下,在你的应用中你可能只希望同一用户在同时登录多次时只能有一个是成功登入你的系统的,通常对应的行为是后一次登录将使前一次登录失效,或者直接限制后一次登录。Spring Security 的 session-management 为我们提供了这种限制。

首先需要我们在 web.xml 中定义如下监听器。

   <listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

在 session-management 元素下有一个 concurrency-control 元素是用来限制同一用户在应用中同时允许存在的已经通过认证的 session 数量。这个值默认是 1,可以通过 concurrency-control 元素的 max-sessions 属性来指定。

   <security:http auto-config="true">
...
<security:session-management>
<security:concurrency-control max-sessions="1"/>
</security:session-management>
...
</security:http>

当同一用户同时存在的已经通过认证的 session 数量超过了 max-sessions 所指定的值时,Spring Security 的默认策略是将先前的设为无效。如果要限制用户再次登录可以设置 concurrency-control 的 error-if-maximum-exceeded 的值为 true。

   <security:http auto-config="true">
...
<security:session-management>
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
</security:session-management>
...
</security:http>

设置 error-if-maximum-exceeded 为 true 后如果你之前已经登录了,然后想再次登录,那么系统将会拒绝你的登录,同时将重定向到由 form-login 指定的 authentication-failure-url。如果你的再次登录是通过 Remember-Me 来完成的,那么将不会转到 authentication-failure-url,而是返回未授权的错误码 401 给客户端,如果你还是想重定向一个指定的页面,那么你可以通过 session-management 的 session-authentication-error-url 属性来指定,同时需要指定该 url 为不受 Spring Security 管理,即通过 http 元素设置其 secure=”none”。

   <security:http security="none" pattern="/none/**" />
<security:http>
<security:form-login/>
<security:logout/>
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<!-- session-authentication-error-url 必须是不受 Spring Security 管理的 -->
<security:session-management session-authentication-error-url="/none/session_authentication_error.jsp">
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
</security:session-management>
<security:remember-me data-source-ref="dataSource"/>
</security:http>

在上述配置中我们配置了 session-authentication-error-url 为 “/none/session_authentication_error.jsp”,同时我们通过 指定了以 “/none” 开始的所有 URL 都不受 Spring Security 控制,这样当用户进行登录以后,再次通过 Remember-Me 进行自动登录时就会重定向到 “/none/session_authentication_error.jsp” 了。

在上述配置中为什么我们需要通过 指定我们的 session-authentication-error-url 不受 Spring Security 控制呢?把它换成 不行吗?这就涉及到之前所介绍的它们两者之间的区别了。前者表示不使用任何 Spring Security 过滤器,自然也就不需要通过 Spring Security 的认证了,而后者是会被 Spring Security 的 FilterChain 进行过滤的,只是其对应的 URL 可以匿名访问,即不需要登录就可访问。使用后者时,REMEMBER_ME_FILTER 检测到用户没有登录,同时其又提供了 Remember-Me 的相关信息,这将使得 REMEMBER_ME_FILTER 进行自动登录,那么在自动登录时由于我们限制了同一用户同一时间只能登录一次,后来者将被拒绝登录,这个时候将重定向到 session-authentication-error-url,重定向访问 session-authentication-error-url 时,经过 REMEMBER_ME_FILTER 时又会自动登录,这样就形成了一个死循环。所以 session-authentication-error-url 应当使用 设置为不受 Spring Security 控制,而不是使用 。

此外,可以通过 expired-url 属性指定当用户尝试使用一个由于其再次登录导致 session 超时的 session 时所要跳转的页面。同时需要注意设置该 URL 为不需要进行认证。

   <security:http auto-config="true">
<security:form-login/>
<security:logout/>
<security:intercept-url pattern="/expired.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<security:session-management>
<security:concurrency-control max-sessions="1" expired-url="/expired.jsp" />
</security:session-management>
</security:http>

session 固定攻击保护

session 固定是指服务器在给客户端创建 session 后,在该 session 过期之前,它们都将通过该 session 进行通信。session 固定攻击是指恶意攻击者先通过访问应用来创建一个 session,然后再让其他用户使用相同的 session 进行登录(比如通过发送一个包含该 sessionId 参数的链接),待其他用户成功登录后,攻击者利用原来的 sessionId 访问系统将和原用户获得同样的权限。Spring Security 默认是对 session 固定攻击采取了保护措施的,它会在用户登录的时候重新为其生成一个新的 session。如果你的应用不需要这种保护或者该保护措施与你的某些需求相冲突,你可以通过 session-management 的 session-fixation-protection 属性来改变其保护策略。该属性的可选值有如下三个。

  • migrateSession:这是默认值。其表示在用户登录后将新建一个 session,同时将原 session 中的 attribute 都 copy 到新的 session 中。
  • none:表示继续使用原来的 session。
  • newSession:表示重新创建一个新的 session,但是不 copy 原 session 拥有的 attribute。

Spring Security 入门(1-7)Spring Security - Session管理的更多相关文章

  1. spring boot 入门一 构建spring boot 工程

    最近在学习Spring boot,所以想通过博客的形式和大家分享学习的过程,同时也为了更好的学习技术,下面直接进入Spring boot的世界. 简介 spring boot 它的设计目的就是为例简化 ...

  2. spring Boot 入门--为什么用spring boot

    为什么用spring boot 回答这个问题不得不说下spring 假设你受命用Spring开发一个简单的Hello World Web应用程序.你该做什么? 我能想到一些 基本的需要.  一个项目 ...

  3. Spring Security构建Rest服务-1100-单机Session管理

    Session失效时间: springboot配置session失效时间,只需要在application.properties里配置 #session超时时间,低于60秒按60秒server.sess ...

  4. Spring Boot入门篇(基于Spring Boot 2.0系列)

    1:概述: Spring Boot是用来简化Spring应用的初始化开发过程. 2:特性: 创建独立的应用(jar|war形式); 需要用到spring-boot-maven-plugin插件 直接嵌 ...

  5. 通过Spring Session实现新一代的Session管理

    长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...

  6. 转:通过Spring Session实现新一代的Session管理

    长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...

  7. Spring框架学习(7)spring mvc入门

    内容源自:spring mvc入门 一.spring mvc和spring的关系 spring mvc是spring框架提供的七层体系架构中的一个层,是spring框架的一部分,是spring用于处理 ...

  8. 通过 Spring Session 实现新一代的 Session 管理

    长期以来,session 管理就是企业级 Java 中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原 ...

  9. Spring Security 入门

    一.Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配 ...

随机推荐

  1. Java中String字符串常量池总结

    最近到广州某建站互联网公司面试,当时面试官问假设有两个字符串String a="abc",String b = "abc";问输出a==b是true还是fals ...

  2. A Proof of Stake Design Philosophy - PoS权益证明设计理念

    之前在EthFans上看到了关于PoS(权益证明)的相关文章(原文链接),本着学习的态度,对这篇文章进行了翻译.第一次翻译关于区块链的文章,有些单词及句子的措辞还不是很准确,如果发现有翻译的不恰当的地 ...

  3. 【Unity与23种设计模式】观察者模式(Observer)

    GoF中定义: "在对象之间定义一个一对多的连接方法,当一个对象变换状态时,其他关联的对象都会自动收到通知." 现实中,社交网络就是个例子. 以前的报社,每次出新刊的时候, 报刊便 ...

  4. LOOKUP函数入门

    2018-02-11  作者:ExcelHome  阅读:22045次       转载请注明来源"ExcelHome"并保留原文链接.固定链接:http://www.excelh ...

  5. python函数名称空间

    一.命名空间概念 命名空间(name space),若变量x=1,1存放在内存中,命名空间是存放名字x.x与1绑定关系的地方.命名空间分三种: locals:函数内的名称空间,包括局部变量和形参 gl ...

  6. CI框架传递数组到view层问题记录

    给大家分享一下在做页面显示天气预报功能中遇到的问题和解决方法!! 项目开发中,我用的天气预报API是心知天气的免费接口.关于天气预报接口,可用的有很多,看需求怎么要求了!有兴趣的小伙伴可以链接到这个地 ...

  7. Django之ORM基础

    ORM简介 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...

  8. python之Redis的字符串类型操作

    redis的数据类型: 字符串型    哈希     列表     集合     有序集合 1.String(字符串类型) set  命令:   设置一个键和值,键存在则只覆盖,返回ok > s ...

  9. Spring Boot 2.0(五):Docker Compose + Spring Boot + Nginx + Mysql 实践

    我知道大家这段时间看了我写关于 docker 相关的几篇文章,不疼不痒的,仍然没有感受 docker 的便利,是的,我也是这样认为的,I know your felling . 前期了解概念什么的确实 ...

  10. Java多线程:CopyOnWrite容器

    一.什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然 ...