使用Spring Security控制会话
1.概述
在本文中,我们将说明Spring Security如何允许我们控制HTTP会话。此控件的范围从会话超时到启用并发会话和其他高级安全配置。
2.会话何时创建?
我们可以准确控制会话何时创建以及Spring Security如何与之交互:
- always - 如果一个会话尚不存在,将始终创建一个会话
- ifRequired - 仅在需要时创建会话(默认)
- never - 框架永远不会创建会话本身,但如果它已经存在,它将使用一个
- stateless - Spring Security不会创建或使用任何会话
<http create-session="ifRequired">...</http>
Java配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}
了解此配置仅控制Spring Security的功能非常重要 - 而不是整个应用程序。如果我们不指示Spring Security,可能无法创建会话,但我们的应用程序可能会!
默认情况下,Spring Security会在需要时创建会话 - 这是“ifRequired”。
对于更无状态的应用程序,“never”选项将确保Spring Security本身不会创建任何会话;但是,如果应用程序创建了一个,那么Spring Security将使用它。
最后,最严格的会话创建选项 - “stateless” - 保证应用程序根本不会创建任何会话。
这是在Spring 3.1中引入的,它将有效地跳过部分Spring Security过滤器链。主要是会话相关的部分,如HttpSessionSecurityContextRepository,SessionManagementFilter,RequestCacheFilter。
这些更严格的控制机制直接暗示不使用cookie,所以每个请求都需要重新进行身份验证。这种无状态架构适用于REST API及其无状态约束。它们也适用于基本和摘要式身份验证等身份验证机制。
3. Under The Hood
在执行身份验证过程之前,Spring Security将运行一个负责在请求之间存储安全上下文的过滤器-SecurityContextPersistenceFilter。上下文将根据策略存储 - 默认情况下为HttpSessionSecurityContextRepository - 它使用HTTP会话作为存储。对于strict create-session =“stateless”属性,此策略将替换为另一个 - NullSecurityContextRepository - 并且不会创建或使用会话来保留上下文。
4.并发会话控制
当已经过身份验证的用户尝试再次进行身份验证时,应用程序可以通过以下几种方式之一处理该事件。它可以使用户的活动会话无效,并使用新会话再次对用户进行身份验证,或者允许两个会话同时存在。
启用并发会话控制支持的第一步是在web.xml中添加以下侦听器:
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
或者将其定义为Bean - 如下所示:
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
这对于确保在销毁会话时通知Spring Security会话注册表是至关重要。
要为同一用户启用允许多个并发会话的方案,应在XML配置中使用元素:
<http ...>
<session-management>
<concurrency-control max-sessions="2" />
</session-management>
</http>
或者,通过Java配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().maximumSessions(2)
}
5.会话超时
会话超时后,如果用户发送的会话ID已过期,则会将其重定向到可通过命名空间配置的URL:
<session-management>
<concurrency-control expired-url="/sessionExpired.html" ... />
</session-management>
同样,如果用户发送的会话ID未过期但完全无效,则它们也会被重定向到可配置的URL:
<session-management invalid-session-url="/invalidSession.html">
...
</session-management>
相应的Java配置:
http.sessionManagement()
.expiredUrl("/sessionExpired.html")
.invalidSessionUrl("/invalidSession.html");
6.防止使用URL参数进行会话跟踪
在URL中公开会话信息的安全风险越来越大(从2007年的第7位到2013年在OWASP排行榜前10位的第2位)。
从Spring 3.0开始,现在可以通过在命名空间中设置disable-url-rewriting =“true”来禁用将jsessionid附加到URL的URL重写逻辑。
或者,从Servlet 3.0开始,也可以在web.xml中配置会话跟踪机制:
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
编程方式
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
这将选择存储JSESSIONID的位置 - 在cookie或URL参数中。
7. Spring Security的会话固定保护
该框架通过配置在用户已有会话的情况但尝试再次进行身份验证时,提供了针对典型会话固定攻击的保护:
<session-management session-fixation-protection="migrateSession"> ...
相应的Java配置:
http.sessionManagement()
.sessionFixation().migrateSession()
默认情况下,Spring Security启用了此保护(“migrateSession”) - 在身份验证时,会创建一个新的HTTP会话,旧的会话将失效,旧会话的属性将被复制。
如果这不是所需的行为,则可以使用其他两个选项:
- 设置“none”时,原始会话不会失效
- 设置“newSession”时,将创建一个干净的会话,而不会复制旧会话中的任何属性
8.安全会话Cookie
接下来,我们将讨论如何保护会话cookie。
我们可以使用httpOnly和secure标签来保护我们的会话cookie:
- httpOnly:如果为true,那么浏览器脚本将无法访问cookie
- secure:如果为true,则cookie将仅通过HTTPS连接发送
我们可以在web.xml中为会话cookie设置这些标志:
<session-config>
<session-timeout>1</session-timeout>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
从Java servlet 3开始,此配置选项可用。默认情况下,http-only为true且secure为false。
我们来看看相应的Java配置:
public class MainWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
// ...
sc.getSessionCookieConfig().setHttpOnly(true);
sc.getSessionCookieConfig().setSecure(true);
}
}
如果我们使用Spring Boot,我们可以在application.properties中设置这些标志:
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
最后,我们还可以使用Filter手动实现此目的:
public class SessionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
Cookie[] allCookies = req.getCookies();
if (allCookies != null) {
Cookie session =
Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID"))
.findFirst().orElse(null);
if (session != null) {
session.setHttpOnly(true);
session.setSecure(true);
res.addCookie(session);
}
}
chain.doFilter(req, res);
}
}
9.Session使用
9.1。 Session Scoped Beans
只需在web-Context中,使用@Scope注释声明的bean:
@Component
@Scope("session")
public class Foo { .. }
或者使用XML:
<bean id="foo" scope="session"/>
然后,bean可以简单地注入另一个bean:
@Autowired
private Foo theFoo;
Spring会将新bean绑定到HTTP Session的生命周期。
9.2。将会话注入控制器
原始HTTP会话也可以直接注入Controller方法:
@RequestMapping(..)
public void fooMethod(HttpSession session) {
session.addAttribute(Constants.FOO, new Foo();
//...
Foo foo = (Foo) session.getAttribute(Constants.Foo);
}
9.3。获取会话
当前的HTTP Session也可以通过原始Servlet API以编程方式获得:
ServletRequestAttributes attr = (ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes();
HttpSession session= attr.getRequest().getSession(true); // true == allow create
10.总结
在本文中,我们讨论了使用Spring Security管理Sessions。此外,Spring Reference包含一个非常好的会话管理常见问题解答。
与往常一样,本文中提供的代码可以在Github上获得。这是一个基于Maven的项目,因此它应该很容易导入和运行。
使用Spring Security控制会话的更多相关文章
- Spring Security控制权限
Spring Security控制权限 1,配置过滤器 为了在项目中使用Spring Security控制权限,首先要在web.xml中配置过滤器,这样我们就可以控制对这个项目的每个请求了. < ...
- spring security控制session
spring security控制session本文给你描述在spring security中如何控制http session.包括session超时.启用并发session以及其他高级安全配置. 创 ...
- spring security 管理会话 多个用户不可以使用同一个账号登录系统
多个用户不能使用同一个账号同时登陆系统. 1. 添加监听器 在web.xml中添加一个监听器,这个监听器会在session创建和销毁的时候通知Spring Security. <listener ...
- spring security防御会话伪造session攻击
1. 攻击场景 session fixation会话伪造攻击是一个蛮婉转的过程. 比如,当我要是使用session fixation攻击你的时候,首先访问这个网站,网站会创建一个会话,这时我可以把附有 ...
- spring security 控制用户信息用户加密 缓存用户信息
1. MD5加密 任何一个正式的企业应用中,都不会在数据库中使用明文来保存密码的,我们在之前的章节中都是为了方便起见没有对数据库中的用户密码进行加密,这在实际应用中是极为幼稚的做法.可以想象一下,只要 ...
- 结合Spring Security进行web应用会话安全管理
在本文中,将为大家说明如何结合Spring Security 和Spring Session管理web应用的会话. 一.Spring Security创建使用session的方法 Spring Sec ...
- Spring Security 5.0.x 参考手册 【翻译自官方GIT-2018.06.12】
源码请移步至:https://github.com/aquariuspj/spring-security/tree/translator/docs/manual/src/docs/asciidoc 版 ...
- Spring Security(13)——session管理
1.1 检测session超时 1.2 concurrency-control 1.3 session 固定攻击保护 Spring Security通过http元素下的子元素s ...
- Spring Security教程系列(一)基础篇-1
第 1 章 一个简单的HelloWorld 第 1 章 一个简单的HelloWorld Spring Security中可以使用Acegi-1.x时代的普通配置方式,也可以使用从2.0时代才出现的命名 ...
随机推荐
- 多用GCD,少用performSelect系列方法
例如,要延后执行某项任务,可以有下面两种实现方式,而我们应该优先考虑第二种: // Using performSelect: withObject: afterDelay: [self perform ...
- 解决Pods Unable to find a specification for `xxxxx`问题
错误信息为 Unable to find a specification for *RMQClient* (~> 1.x.x) depended upon by Podfile 刚开始以为这个已 ...
- Java服务器端 API 错误码设计总结
1.对于API结果返回,定义BaseResult 类 拥有success,errorCode,errorMsg个3个基本参数,success使用Boolean类型,errorCode使用Integer ...
- 【Effective C++】实现
条款26:尽可能延后变量定义式的出现时间 有些对象,你可能过早的定义它,而在代码执行的过程中发生了导常,造成了开始定义的对象并没有被使用,而付出了构造成本来析构成本. 所以我们应该在定义对象时,尽可能 ...
- AndroidPageObjectTest_Chained.java
以下代码使用ApiDemos-debug.apk进行测试 //这个脚本用于演示PageFactory的功能:链式注解@AndroidFindBys.@IOSFindBys.具体用法参考页面类的代码. ...
- 步入C编程的第一天
我想学ruby以后开发网站,但ruby是高级语言,隐藏了许多底层的东西,因此先熟悉c语言 首先c程序的文件名是以.c结尾的 c程序的格式: 第一行#include<stdio.h> #是一 ...
- ansible 文件模块,很实用
摘自: http://blog.csdn.net/kellyseeme/article/details/50545521
- CISCO-配置SSH
PC直接连在交换机端口上,PC的ip地址是:192.168.1.1/24 在交换机的操作步骤如下: 1.设置交换机管理ip Switch#conf t Switch(config)#int vlan ...
- 最基本PSO算法的C++实现
按照James Kennedy & Russell Eberhart (1995)的版本,算法过程如下: [x*] = PSO() P = Particle_Initialization(); ...
- 深度学习之卷积神经网络(CNN)学习
1.卷积神经网络中卷积的核心意义是什么?每一组卷集核 权重是一个抽特征的滤波器, 从卷集核的角度抽取特征 2.卷积神经网络很好的特性参数共享机制每一个神经元固定一组a x b x c(图像的通道数) ...