zoukankan      html  css  js  c++  java
  • Spring Security Session并发控制原理解析

    当使用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>
  • 相关阅读:
    20155328 《网络攻防》 实验一:PC平台逆向破解(5)M
    20155328 《信息安全系统设计基础》 课程总结
    构建之法
    20155327 2017-2018-2《Java程序设计》课程总结
    20155327 实验五 网络编程与安全
    20155327 网络对抗 实验
    20155327 Exp9 Web安全基础
    20155327 EXP8 Web基础
    20155327 实验四 Android程序设计
    20155327 李百乾 Exp7 网络欺诈防范
  • 原文地址:https://www.cnblogs.com/lzmrex/p/10684014.html
Copyright © 2011-2022 走看看