All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.beangle.security.session.cache.CacheSessionRegistry.scala Maven / Gradle / Ivy

/*
 * Beangle, Agile Development Scaffold and Toolkit
 *
 * Copyright (c) 2005-2015, Beangle Software.
 *
 * Beangle is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Beangle is distributed in the hope that it will be useful.
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Beangle.  If not, see .
 */
package org.beangle.security.session.jdbc

import java.io.{ InputStream, ObjectInputStream }
import java.{ util => ju }
import java.util.Timer
import org.beangle.commons.bean.Initializing
import org.beangle.commons.cache.CacheManager
import org.beangle.commons.event.EventPublisher
import org.beangle.commons.lang.Objects
import org.beangle.data.jdbc.query.JdbcExecutor
import org.beangle.security.authc.Account
import org.beangle.security.session.profile.{ ProfileChangeEvent, ProfiledSessionRegistry }
import org.beangle.security.session.util.UpdateDelayGenerator
import org.nustaq.serialization.FSTConfiguration
import javax.sql.DataSource
import org.beangle.security.session.SessionRegistry
import org.beangle.security.session.LogoutEvent
import org.beangle.security.session.DefaultSession
import org.beangle.security.session.SessionBuilder
import org.beangle.security.session.DefaultSessionBuilder
import org.beangle.security.session.Session
/**
 * 基于数据库的session注册表
 */
class CacheSessionRegistry(dataCacheManager: CacheManager, statusCacheManager: CacheManager) extends SessionRegistry
    with EventPublisher {

  private val fstconf = FSTConfiguration.createDefaultConfiguration()

  private val accessDelayMillis = new UpdateDelayGenerator().generateDelayMilliTime()

  private val dataCache = dataCacheManager.getCache("session_data", classOf[String], classOf[Session.Data])

  private val statusCache = statusCacheManager.getCache("session_status", classOf[String], classOf[Session.Status])

  private val timeout = dataCache.ttl

  var builder: SessionBuilder = DefaultSessionBuilder

  var cleaner: SessionCleaner = _

  override def register(sessionId: String, info: Account, client: Session.Client): Session = {
    val existed = get(sessionId).orNull
    val principal = info.getName
    // 是否为重复注册
    if (null != existed && Objects.equals(existed.principal, principal)) {
      existed
    } else {
      if (null != existed) remove(sessionId, " expired with replacement."); // 注销同会话的其它账户
      val session = builder.build(sessionId, this, info, client, System.currentTimeMillis(), timeout) // 新生
      save(session)
      //      publish(new LoginEvent(session))
      session
    }
  }

  override def remove(sessionId: String): Option[Session] = {
    remove(sessionId, null)
  }

  override def access(sessionId: String, accessAt: Long, accessed: String): Option[Session] = {
    get(sessionId) match {
      case s @ Some(session) =>
        if ((accessAt - session.status.lastAccessAt) > accessDelayMillis) {
          //the session was killed by some one,next access will issue login
//          if (dataCache.touch(session.id)) {
//            statusCache.put(session.id, new Session.DefaultStatus(accessAt))
//          } else {
//            dataCache.evict(session.id)
//            statusCache.evict(session.id)
//          }
        }
        s
      case None => None
    }
  }

  override def get(sessionId: String): Option[Session] = {
    if (null == sessionId) return None

    val data = dataCache.get(sessionId).orNull
    var status = statusCache.get(sessionId).orNull
    if (null == data) {
      if (null == status) statusCache.evict(sessionId)
      None
    } else {
      if (null == status) {
        status = new Session.DefaultStatus(System.currentTimeMillis)
        statusCache.put(sessionId, status)
      }
      Some(builder.build(sessionId, this, data, status))
    }
  }

  private def remove(sessionId: String, reason: String): Option[Session] = {
    val s = get(sessionId)
    s foreach { session =>
      publish(new LogoutEvent(session, reason))
      dataCache.evict(sessionId)
      statusCache.evict(sessionId)
    }
    s
  }

  private def save(session: Session): Unit = {
    val s = session.asInstanceOf[DefaultSession]
    val sessionId = s.id
    dataCache.putIfAbsent(sessionId, s.data)
    statusCache.put(sessionId, s.status) // Given the status cache is local cache
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy