Package org.beangle.security.monitor.auth.session.service

Source Code of org.beangle.security.monitor.auth.session.service.DefaultSessionController

package org.beangle.security.monitor.auth.session.service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.beangle.commons.collection.ListUtil;
import org.beangle.commons.collection.MapUtil;
import org.beangle.security.User;
import org.beangle.security.UserCategory;
import org.beangle.security.monitor.Authentication;
import org.beangle.security.monitor.AuthenticationException;
import org.beangle.security.monitor.OnlineActivity;
import org.beangle.security.monitor.auth.session.CategoryProfile;
import org.beangle.security.monitor.auth.session.SessionIdentifierAware;
import org.beangle.security.monitor.auth.session.SessionProfile;
import org.beangle.security.monitor.auth.session.SessionProfileProvider;
import org.beangle.security.monitor.auth.session.SessionRegistry;
import org.beangle.security.monitor.auth.session.model.OnlineActivityBean;
import org.beangle.security.monitor.auth.ui.UserDetails;
import org.beangle.security.monitor.auth.web.WebUserDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultSessionController implements ProfileSessionController {
  private final Logger logger = LoggerFactory.getLogger(DefaultSessionController.class);

  protected SessionRegistry sessionRegistry;

  /** 用户类型配置提供服务 */
  protected SessionProfileProvider profileProvider;

  /** 各类监测类型的监测数据 */
  protected Map<UserCategory, OnlineProfile> profileMap = MapUtil.newHashMap();

  /** 是否加载了用户配置 */
  private boolean loaded = false;

  private boolean exceptionIfMaximumExceeded = false;

  /**
   * allowableSessionsExceeded
   *
   * @param sessionId
   * @param sessions
   * @param allowableSessions
   * @param registry
   * @see checkAuthenticationAllowed
   */
  protected boolean allowableSessionsExceeded(String sessionId, List<OnlineActivity> sessions,
      int allowableSessions, SessionRegistry registry) {
    if (exceptionIfMaximumExceeded || (sessions == null)) {
      return false;
    }
    // Determine least recently used session, and mark it for invalidation
    OnlineActivity leastRecentlyUsed = null;
    for (int i = 0; i < sessions.size(); i++) {
      if ((leastRecentlyUsed == null)
          || sessions.get(i).getLastAccessAt()
              .before(leastRecentlyUsed.getLastAccessAt())) {
        leastRecentlyUsed = (OnlineActivity) sessions.get(i);
      }
    }

    leastRecentlyUsed.expireNow();
    return true;
  }

  public boolean checkAuthenticationAllowed(Authentication request)
      throws AuthenticationException {
    Object principal = request.getPrincipal();
    String sessionId = ((SessionIdentifierAware) request.getDetails()).getSessionId();
    List<OnlineActivity> sessions = sessionRegistry.getOnlineActivities(principal, false);
    int sessionCount = 0;
    if (sessions != null) {
      sessionCount = sessions.size();
    }
    int allowableSessions = getMaximumSessionsForThisUser(request);

    if (sessionCount < allowableSessions) {
      return true;
    } else if (allowableSessions == -1) {
      return true;
    } else if (sessionCount == allowableSessions) {
      for (int i = 0; i < sessionCount; i++) {
        if ((sessions.get(i)).getSessionid().equals(sessionId)) {
          return true;
        }
      }
    }
    return allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry);
  }

  public int getMax() {
    int max = 0;
    for (OnlineProfile element : profileMap.values()) {
      max += element.getCategoryProfile().getCapacity();
    }
    return max;
  }

  public int getMax(UserCategory category) {
    return profileMap.get(category).getCategoryProfile().getCapacity();
  }

  public int getInactiveInterval(UserCategory category) {
    return profileMap.get(category).getCategoryProfile().getInactiveInterval();
  }

  public int getOnlineCount() {
    int online = 0;
    for (OnlineProfile element : profileMap.values()) {
      online += element.getOnline();
    }
    return online;
  }

  public int getOnlineCount(UserCategory category) {
    return ((OnlineProfile) profileMap.get(category)).getOnline();
  }

  public boolean isMaxArrived() {
    return getOnlineCount() >= getMax();
  }

  public boolean isMaxArrived(UserCategory category) {
    return getOnlineCount(category) >= getMax(category);
  }

  public List<OnlineProfile> getOnlineProfiles() {
    return ListUtil.newArrayList(profileMap.values());
  }

  // FIXME 动态更新配置
  // public void setCategoryProfile(UserCategory category, CategoryProfile
  // profile) {
  // ((OnlineProfile) profileMap.get(category)).setCategoryProfile(profile);
  // }

  public void changeCategory(String sessionId, UserCategory category) {
    OnlineActivityBean record = (OnlineActivityBean) sessionRegistry
        .getOnlineActivity(sessionId);
    if (!record.getCategory().equals(category)) {
      profileMap.get(record.getCategory()).left();
      profileMap.get(category).reserve();
      record.setCategory(category);
    }
  }

  /**
   * 注销会话
   */
  public OnlineActivity removeAuthentication(String sessionId) {
    OnlineActivity info = sessionRegistry.remove(sessionId);
    if (null != info) {
      UserCategory category = info.getCategory();
      OnlineProfile profile = ((OnlineProfile) profileMap.get(category));
      profile.left();
    }
    return info;
  }

  /**
   * 根据用户身份确定单个用户的最大会话数<br>
   * Method intended for use by subclasses to override the maximum number of
   * sessions that are permitted for a particular authentication.
   *
   * @param authentication
   *            to determine the maximum sessions for
   * @return either -1 meaning unlimited, or a positive integer to limit
   *         (never zero)
   */
  protected int getMaximumSessionsForThisUser(Authentication auth) {
    loadProfilesWhenNecessary();
    UserDetails details = (UserDetails) auth.getDetails();
    OnlineProfile profile = (OnlineProfile) profileMap.get(details.getCategory());
    if (null == profile) {
      logger.error("cannot find profile for {}", details.getCategory().getId());
      throw new RuntimeException("cannot find profile:" + details.getCategory().getName());
    }
    return profile.getCategoryProfile().getUserMaxSessions();
  }

  /**
   * 注册用户
   */
  public void registerAuthentication(Authentication authentication) {
    WebUserDetails details = (WebUserDetails) authentication.getDetails();
    OnlineProfile profile = (OnlineProfile) profileMap.get(details.getCategory());
    OnlineActivity existed = getOnlineActivity(details.getSessionId());
    String sessionId = details.getSessionId();
    Object principal = authentication.getPrincipal();
    OnlineActivity newOne = OnlineActivityBuilder.build(principal, authentication.getDetails(),
        sessionId, new Date());
    // 原先没有的要占座
    if (null == existed) {
      if (!profile.reserve())
        throw new AuthenticationException(Authentication.ERROR_OVERMAX);
    }
    // calculateOnline();
    sessionRegistry.register(sessionId, principal, newOne);
    // logger.debug("Register session {} for {}", sessionId, principal);
  }

  public void calculateOnline() {
    int all = 0;
    for (UserCategory category : profileMap.keySet()) {
      OnlineProfile p = (OnlineProfile) profileMap.get(category);
      all += p.getOnline();
    }
    if (all != sessionRegistry.count()) {
      logger.info("start calculate...registry {} profile {}", new Integer(sessionRegistry
          .count()), new Integer(all));
      if (all > 0)
        throw new RuntimeException("");
      Map<UserCategory, OnlineProfile> newProfileMap = MapUtil.newHashMap();
      for (final UserCategory category : profileMap.keySet()) {
        OnlineProfile profile = (OnlineProfile) profileMap.get(category);
        OnlineProfile newProfile = new OnlineProfile();
        newProfile.setCategoryProfile(profile.getCategoryProfile());
        newProfileMap.put(category, newProfile);
      }

      List<OnlineActivity> infos = sessionRegistry.getOnlineActivities();
      for (final OnlineActivity info : infos) {
        OnlineProfile profile = newProfileMap.get(info.getCategory());
        profile.reserve();
      }
      profileMap.putAll(newProfileMap);
    }
  }

  public Collection<OnlineActivity> getOnlineActivities(UserCategory category) {
    List<OnlineActivity> activities = ListUtil.newArrayList();
    for (OnlineActivity oa : sessionRegistry.getOnlineActivities()) {
      if (oa.getCategory().equals(category)) {
        activities.add(oa);
      }
    }
    return activities;
  }

  public void loadProfilesWhenNecessary() {
    if (!loaded) {
      synchronized (this) {
        if (loaded)
          return;
        loadProfiles();
      }
    }
  }

  public void loadProfiles() {
    if (null == profileProvider) {
      loaded = true;
      logger.warn("Cannot load profile for  profileProvider not found!");
      return;
    }
    SessionProfile sessionProfile = profileProvider.getProfile();
    if (null != sessionProfile) {
      for (CategoryProfile cp : sessionProfile.getCategoryProfiles().values()) {
        int initOnline=0;
        OnlineProfile existed=profileMap.get(cp.getCategory());
        if(null!=existed){
          initOnline=existed.getOnline();
        }
        profileMap.put(cp.getCategory()new OnlineProfile(cp,initOnline));
        logger.info(cp.toString());
      }
    }
    loaded = !(profileMap.isEmpty());
  }

  public Collection<OnlineActivity> getOnlineActivities(User user) {
    return sessionRegistry.getOnlineActivities(user.getName(), true);
  }

  public SessionProfileProvider getProfileProvider() {
    return profileProvider;
  }

  public void setProfileProvider(SessionProfileProvider profileProvider) {
    this.profileProvider = profileProvider;
  }

  public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) {
    this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
  }

  public OnlineActivity getOnlineActivity(String sessionId) {
    return sessionRegistry.getOnlineActivity(sessionId);
  }

  public List<OnlineActivity> getOnlineActivities() {
    return sessionRegistry.getOnlineActivities();
  }

  public boolean isRegisted(Object principal) {
    return sessionRegistry.isRegisted(principal);
  }

  public void setSessionRegistry(SessionRegistry sessionRegistry) {
    this.sessionRegistry = sessionRegistry;
  }
}
TOP

Related Classes of org.beangle.security.monitor.auth.session.service.DefaultSessionController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.