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

org.beangle.security.session.jdbc.registry.scala Maven / Gradle / Ivy

The newest version!
package org.beangle.security.session.jdbc

import java.io.{ InputStream, ObjectInputStream, Serializable => jSerializable }
import java.{ util => ju }

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, AuthenticationInfo }
import org.beangle.security.session.{ AbstractSessionRegistry, DefaultSession, DefaultSessionProfile, LoginEvent, LogoutEvent, Session, SessionBuilder, SessionKey, SessionProfile }

class DBSessionRegistry(val builder: SessionBuilder, val executor: JdbcExecutor)
  extends AbstractSessionRegistry with EventPublisher {

  val columns = "id,account,principal,login_at,os,agent,host,server,expired_at,remark,timeout,last_access_at,last_accessed,category"

  val table = "se_sessoin_infoes"

  private def convert(datas: Seq[Seq[_]]): Seq[Session] = {
    for (data <- datas) yield convert(data)
  }

  private def convert(data: Seq[_]): Session = {
    val account = new ObjectInputStream(data(1).asInstanceOf[InputStream]).readObject().asInstanceOf[Account]
    val session = new DefaultSession(data(0).asInstanceOf[jSerializable], account, this, data(2).asInstanceOf[ju.Date], data(3).toString, data(4).toString, data(5).toString)
    session.server = data(6).toString
    session.expiredAt = if (null == data(7)) null else data(7).asInstanceOf[ju.Date]
    session.remark = if (null == data(8)) null else data(8).toString
    session.timeout = data(9).asInstanceOf[Number].shortValue()
    session.lastAccessAt = data(10).asInstanceOf[ju.Date]
    session.lastAccessed = if (null == data(11)) null else data(11).toString
    session
  }

  private def save(s: Session): Unit = {
    executor.update(s"insert into $table ($columns) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
      s.id, s.principal.getName, s.loginAt, s.os, s.agent, s.host, s.server, s.expiredAt,
      s.remark, s.timeout, s.lastAccessAt, s.lastAccessed, category(s.principal))
  }

  override def register(info: AuthenticationInfo, key: SessionKey): Session = {
    val existed = get(key).orNull
    val principal = info.getName
    // 是否为重复注册
    if (null != existed && Objects.equals(existed.principal, principal)) {
      existed
    } else {
      // 争取名额
      tryAllocate(key, info)
      // 注销同会话的其它账户
      if (null != existed) remove(key, " expired with replacement.");
      // 新生
      val session = builder.build(key, info, this)
      save(session);
      publish(new LoginEvent(session))
      session
    }
  }

  override def remove(key: SessionKey): Option[Session] = remove(key, null)

  private def remove(key: SessionKey, reason: String): Option[Session] = {
    val s = get(key)
    s foreach { session =>
      release(session)
      session.remark(reason)
      publish(new LogoutEvent(session))
      executor.update(s"delete from $table where id=?", key.sessionId)
    }
    s
  }

  override def onExpire(session: Session): Unit = {
    release(session)
    executor.update(s"update $table set expired_at=? where id=?", session.expiredAt, session.id) > 0
  }

  // FIXME update db to offen
  override def onAccess(session: Session, accessAt: ju.Date, accessed: String): Unit = {
    executor.update(s"update $table set last_access_at=? ,last_accessed=? where id=?", accessAt, accessed, session.id)
  }

  override def get(principal: String, includeExpired: Boolean): Seq[Session] = {
    convert(executor.query(s"select $columns from $table info where info.principal=?" +
      (if (!includeExpired) " and info.expired_at is null" else ""), principal))
  }

  /**
   * Get Expired and last accessed before the time
   */
  def getExpired(lastAccessAt: ju.Date): Seq[Session] = {
    convert(executor.query(s"select $columns from $table info where info.expired_at is not null or info.last_access_at  0
  }

  protected override def release(session: Session): Unit = {
    executor.update("update se_session_stats set on_line=on_line - 1 where on_line>0 and category=?",
      category(session.principal.asInstanceOf[AuthenticationInfo]))
  }

  override def getProfile(auth: AuthenticationInfo): Option[SessionProfile] = {
    val rs = executor.query("select category,capacity,max_session,timeout from se_session_profiles  where category=?", category(auth))
    if (rs.isEmpty) None
    else {
      val data = rs(0)
      val profile = new DefaultSessionProfile(data(0).toString)
      profile.capacity = data(0).asInstanceOf[Number].intValue
      profile.maxSession = data(1).asInstanceOf[Number].intValue
      profile.timeout = data(2).asInstanceOf[Number].shortValue
      Some(profile)
    }
  }

  override def stat(): Unit = {
    executor.update(s"update se_session_stats stat set stat.on_line=(select count(id) from $table " +
      " info where info.expired_at is null and info.category=stat.category)");
  }

  @inline
  private def category(auth: AuthenticationInfo): Any = auth.principal.asInstanceOf[Account].category

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy