当使用spring security 的标签,如下,其中<sec:session-management>对应的SessionManagementFilter。从名字可以看出,这是一个管理Session的过滤器。这个过滤器会拦截每一个请求。然后判断用户有没有认证过。如果已经认证过,则执行Session认证策略。session 认证策略可配置。我们来看看这个过滤器的源代码,具体逻辑就直接在源码上标注。

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

if (request.getAttribute(FILTER_APPLIED) != null) {
chain.doFilter(request, response);
return;
} request.setAttribute(FILTER_APPLIED, Boolean.TRUE); if (!securityContextRepository.containsContext(request)) {// 第一次访问,直接放行
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();//获取认证对象 if (authentication != null && !trustResolver.isAnonymous(authentication)) {//用户已经认证过
// The user has been authenticated during the current request, so call the
// session strategy
try {
sessionAuthenticationStrategy.onAuthentication(authentication,
request, response); //这里是session管理的关键,具体逻辑请看Session认证策略
}
catch (SessionAuthenticationException e) {
// The session strategy can reject the authentication
logger.debug(
"SessionAuthenticationStrategy rejected the authentication object",
e);
SecurityContextHolder.clearContext();
failureHandler.onAuthenticationFailure(request, response, e); return;
}
// Eagerly save the security context to make it available for any possible
// re-entrant
// requests which may occur before the current request completes.
// SEC-1396.
securityContextRepository.saveContext(SecurityContextHolder.getContext(),
request, response);
}
else {
// No security context or authentication present. Check for a session
// timeout
if (request.getRequestedSessionId() != null
&& !request.isRequestedSessionIdValid()) {
if (logger.isDebugEnabled()) {
logger.debug("Requested session ID "
+ request.getRequestedSessionId() + " is invalid.");
} if (invalidSessionStrategy != null) {
invalidSessionStrategy
.onInvalidSessionDetected(request, response);
return;
}
}
}
} chain.doFilter(request, response);
}

CompositeSessionAuthenticationStrategy.java:

public void onAuthentication(Authentication authentication,
HttpServletRequest request, HttpServletResponse response)
throws SessionAuthenticationException {
for (SessionAuthenticationStrategy delegate : delegateStrategies) {
if (logger.isDebugEnabled()) {
logger.debug("Delegating to " + delegate);
}
delegate.onAuthentication(authentication, request, response);
}
}
ConcurrentSessionControlAuthenticationStrategy.java
/**
* In addition to the steps from the superclass, the sessionRegistry will be updated
* with the new session information.
*/
public void onAuthentication(Authentication authentication,
HttpServletRequest request, HttpServletResponse response) { final List<SessionInformation> sessions = sessionRegistry.getAllSessions(
authentication.getPrincipal(), false); // 根据认证主体获取session int sessionCount = sessions.size();
int allowedSessions = getMaximumSessionsForThisUser(authentication); if (sessionCount < allowedSessions) {
// They haven't got too many login sessions running at present
return;
} if (allowedSessions == -1) {
// We permit unlimited logins
return;
} if (sessionCount == allowedSessions) {
HttpSession session = request.getSession(false); if (session != null) {
// Only permit it though if this request is associated with one of the
// already registered sessions
for (SessionInformation si : sessions) {
if (si.getSessionId().equals(session.getId())) {
return;
}
}
}
// If the session is null, a new one will be created by the parent class,
// exceeding the allowed number
} allowableSessionsExceeded(sessions, allowedSessions, sessionRegistry);
}
protected void allowableSessionsExceeded(List<SessionInformation> sessions,
int allowableSessions, SessionRegistry registry)
throws SessionAuthenticationException {
if (exceptionIfMaximumExceeded || (sessions == null)) {
throw new SessionAuthenticationException(messages.getMessage(
"ConcurrentSessionControlAuthenticationStrategy.exceededAllowed",
new Object[] { Integer.valueOf(allowableSessions) },
"Maximum sessions of {0} for this principal exceeded"));
} // Determine least recently used session, and mark it for invalidation
SessionInformation leastRecentlyUsed = null; for (SessionInformation session : sessions) {
if ((leastRecentlyUsed == null)
|| session.getLastRequest()
.before(leastRecentlyUsed.getLastRequest())) {
leastRecentlyUsed = session;
}
} leastRecentlyUsed.expireNow();
}
 
<sec:http>
  <sec:session-management/>
</sec:http>

Spring Security Session并发控制原理解析的更多相关文章

  1. Spring Security 解析(七) —— Spring Security Oauth2 源码解析

    Spring Security 解析(七) -- Spring Security Oauth2 源码解析   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因 ...

  2. Spring Security 访问控制 源码解析

    上篇 Spring Security 登录校验 源码解析  分析了使用Spring Security时用户登录时验证并返回token过程,本篇分析下用户带token访问时,如何验证用户登录状态及权限问 ...

  3. Spring Security 入门(1-7)Spring Security - Session管理

    参考链接:https://xueliang.org/article/detail/20170302232815082 session 管理 Spring Security 通过 http 元素下的子元 ...

  4. Spring Security Session Time Out

    最近在用Spring Security做登录管理,登陆成功后,页面长时间无操作,超过session的有效期后,再次点击页面操作,页面无反应,需重新登录后才可正常使用系统. 为了优化用户体验,使得在se ...

  5. spring security控制session

    spring security控制session本文给你描述在spring security中如何控制http session.包括session超时.启用并发session以及其他高级安全配置. 创 ...

  6. Spring Security 5.0.x 参考手册 【翻译自官方GIT-2018.06.12】

    源码请移步至:https://github.com/aquariuspj/spring-security/tree/translator/docs/manual/src/docs/asciidoc 版 ...

  7. Spring Security 入门原理及实战

    目录 从一个Spring Security的例子开始 创建不受保护的应用 加入spring security 保护应用 关闭security.basic ,使用form表单页面登录 角色-资源 访问控 ...

  8. 44. Spring Security FAQ春季安全常见问题

    第44.1节,“一般问题” 第44.2节,“常见问题” 第44.3节,“春季安全架构问题” 第44.4节,“常见”如何“请求 44.1 General Questions 第44.1.1节,“Spri ...

  9. Spring Security的使用

    spring security使用目的:验证,授权,攻击防护. 原理:创建大量的filter和interceptor来进行请求的验证和拦截,以此来达到安全的效果. Spring Security主要包 ...

随机推荐

  1. ES进阶--02

    第11节深度探秘搜索技术_案例实战基于dis_max实现best fields策略进行多字段搜索 课程大纲 1.为帖子数据增加content字段 POST /forum/article/_bulk{ ...

  2. 【原创】大数据基础之ElasticSearch(5)重要配置及调优

    Index Settings 重要索引配置 Index level settings can be set per-index. Settings may be: 1 static 静态索引配置 Th ...

  3. springboot配置文件priperties大全

    flyway.baseline-description 执行基线时标记已有Schema的描述. flyway.baseline-on-migrate 在没有元数据表的情况下,针对非空Schema执行迁 ...

  4. 03-django模型(1)

    一.内容回顾 1.路由层 a.简单使用 b.有名分组 c.路由分发 d.反向解析 2.视图层 a.HttpRequest对象 常用的属性 常用方法 b.HttpResponse对象 响应三剑客 3.模 ...

  5. web开篇

    一.内容回顾 1.python基础 2.网络编程 3.并发编程 4.前端 5.数据库(MySQL) 二.今日概要 1.了解Web应用程序的本质 2.Django简介及安装使用 三.今日详细 1.最简单 ...

  6. bzoj 2780

    后缀自动机的应用 首先我们观察到:如果一个询问串的答案不为0,那么这个串一定是至少一个模式串的子串 如果只有一个模式串,那么这个问题可以简单地用什么东西解决掉(比如普通后缀自动机) 而这里有很多模式串 ...

  7. Git基本操作指令

    Git是世界上目前最先进的分布式版本控制系统. 工作原理图: Workspace工作区,Index暂存区,Repository本地仓库区,Remote远程仓库. SVN与Git的最主要的区别? SVN ...

  8. Microsoft Office Word 中的公式自动编号

    先插入公式,#,插入题注(交叉引用),生成了标号.此时整个公式是题注样式.在公式和标号之间插入一个样式分隔符. ____________________________________________ ...

  9. pip命令出现了问题,提示说找不到ssl模块

    Could not find a version that satisfies the requirement pygame (from versions: ) No matching distrib ...

  10. mysql 使用教程 入门

    转载 http://www.cnblogs.com/mr-wid/archive/2013/05/09/3068229.html MySQL有三大类数据类型, 分别为数字.日期\时间.字符串, 这三大 ...