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

com.penglecode.common.web.shiro.session.SimpleSession Maven / Gradle / Ivy

Go to download

commons is a little java tool to make your development easier in your work.

The newest version!
package com.penglecode.common.web.shiro.session;

import java.io.Serializable;
import java.text.DateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.session.ExpiredSessionException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.StoppedSessionException;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.ValidatingSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 由于Shiro默认的SimpleSession持久化字段全是transient的,在应用某些序列化框架时会报错,此实现基本copy自SimpleSession实现,已解决此类问题
 * 
 * @author	  	pengpeng
 * @date	  	2015年3月18日 下午3:28:10
 * @version  	1.0
 */
public class SimpleSession implements ValidatingSession, Serializable {

	private static final long serialVersionUID = 1L;

	private transient static final Logger log = LoggerFactory.getLogger(SimpleSession.class);

    protected static final long MILLIS_PER_SECOND = 1000;
    protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
    protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;

    private Serializable id;
    private Date startTimestamp;
    private Date stopTimestamp;
    private Date lastAccessTime;
    private long timeout;
    private boolean expired;
    private String host;
    private Map attributes;

    public SimpleSession() {
        this.timeout = DefaultSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT;
        this.startTimestamp = new Date();
        this.lastAccessTime = this.startTimestamp;
    }

    public SimpleSession(String host) {
        this();
        this.host = host;
    }

    public Serializable getId() {
        return this.id;
    }

    public void setId(Serializable id) {
        this.id = id;
    }

    public Date getStartTimestamp() {
        return startTimestamp;
    }

    public void setStartTimestamp(Date startTimestamp) {
        this.startTimestamp = startTimestamp;
    }

    /**
     * Returns the time the session was stopped, or null if the session is still active.
     * 

* A session may become stopped under a number of conditions: *

    *
  • If the user logs out of the system, their current session is terminated (released).
  • *
  • If the session expires
  • *
  • The application explicitly calls {@link #stop()}
  • *
  • If there is an internal system error and the session state can no longer accurately * reflect the user's behavior, such in the case of a system crash
  • *
*

* Once stopped, a session may no longer be used. It is locked from all further activity. * * @return The time the session was stopped, or null if the session is still * active. */ public Date getStopTimestamp() { return stopTimestamp; } public void setStopTimestamp(Date stopTimestamp) { this.stopTimestamp = stopTimestamp; } public Date getLastAccessTime() { return lastAccessTime; } public void setLastAccessTime(Date lastAccessTime) { this.lastAccessTime = lastAccessTime; } /** * Returns true if this session has expired, false otherwise. If the session has * expired, no further user interaction with the system may be done under this session. * * @return true if this session has expired, false otherwise. */ public boolean isExpired() { return expired; } public void setExpired(boolean expired) { this.expired = expired; } public long getTimeout() { return timeout; } public void setTimeout(long timeout) { this.timeout = timeout; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public Map getAttributes() { return attributes; } public void setAttributes(Map attributes) { this.attributes = attributes; } public void touch() { this.lastAccessTime = new Date(); } public void stop() { if (this.stopTimestamp == null) { this.stopTimestamp = new Date(); } } protected boolean isStopped() { return getStopTimestamp() != null; } protected void expire() { stop(); this.expired = true; } /** * @since 0.9 */ public boolean isValid() { return !isStopped() && !isExpired(); } /** * Determines if this session is expired. * * @return true if the specified session has expired, false otherwise. */ protected boolean isTimedOut() { if (isExpired()) { return true; } long timeout = getTimeout(); if (timeout >= 0l) { Date lastAccessTime = getLastAccessTime(); if (lastAccessTime == null) { String msg = "session.lastAccessTime for session with id [" + getId() + "] is null. This value must be set at " + "least once, preferably at least upon instantiation. Please check the " + getClass().getName() + " implementation and ensure " + "this value will be set (perhaps in the constructor?)"; throw new IllegalStateException(msg); } // Calculate at what time a session would have been last accessed // for it to be expired at this point. In other words, subtract // from the current time the amount of time that a session can // be inactive before expiring. If the session was last accessed // before this time, it is expired. long expireTimeMillis = System.currentTimeMillis() - timeout; Date expireTime = new Date(expireTimeMillis); return lastAccessTime.before(expireTime); } else { if (log.isTraceEnabled()) { log.trace("No timeout for session with id [" + getId() + "]. Session is not considered expired."); } } return false; } public void validate() throws InvalidSessionException { //check for stopped: if (isStopped()) { //timestamp is set, so the session is considered stopped: String msg = "Session with id [" + getId() + "] has been " + "explicitly stopped. No further interaction under this session is " + "allowed."; throw new StoppedSessionException(msg); } //check for expiration if (isTimedOut()) { expire(); //throw an exception explaining details of why it expired: Date lastAccessTime = getLastAccessTime(); long timeout = getTimeout(); Serializable sessionId = getId(); DateFormat df = DateFormat.getInstance(); String msg = "Session with id [" + sessionId + "] has expired. " + "Last access time: " + df.format(lastAccessTime) + ". Current time: " + df.format(new Date()) + ". Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds (" + timeout / MILLIS_PER_MINUTE + " minutes)"; if (log.isTraceEnabled()) { log.trace(msg); } throw new ExpiredSessionException(msg); } } private Map getAttributesLazy() { Map attributes = getAttributes(); if (attributes == null) { attributes = new HashMap(); setAttributes(attributes); } return attributes; } public Collection getAttributeKeys() throws InvalidSessionException { Map attributes = getAttributes(); if (attributes == null) { return Collections.emptySet(); } return attributes.keySet(); } public Object getAttribute(Object key) { Map attributes = getAttributes(); if (attributes == null) { return null; } return attributes.get(key); } public void setAttribute(Object key, Object value) { if (value == null) { removeAttribute(key); } else { getAttributesLazy().put(key, value); } } public Object removeAttribute(Object key) { Map attributes = getAttributes(); if (attributes == null) { return null; } else { return attributes.remove(key); } } /** * Returns {@code true} if the specified argument is an {@code instanceof} {@code PersistentSession} and both * {@link #getId() id}s are equal. If the argument is a {@code PersistentSession} and either 'this' or the argument * does not yet have an ID assigned, the value of {@link #onEquals(SimpleSession) onEquals} is returned, which * does a necessary attribute-based comparison when IDs are not available. *

* Do your best to ensure {@code PersistentSession} instances receive an ID very early in their lifecycle to * avoid the more expensive attributes-based comparison. * * @param obj the object to compare with this one for equality. * @return {@code true} if this object is equivalent to the specified argument, {@code false} otherwise. */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof SimpleSession) { SimpleSession other = (SimpleSession) obj; Serializable thisId = getId(); Serializable otherId = other.getId(); if (thisId != null && otherId != null) { return thisId.equals(otherId); } else { //fall back to an attribute based comparison: return onEquals(other); } } return false; } /** * Provides an attribute-based comparison (no ID comparison) - incurred only when 'this' or the * session object being compared for equality do not have a session id. * * @param ss the PersistentSession instance to compare for equality. * @return true if all the attributes, except the id, are equal to this object's attributes. * @since 1.0 */ protected boolean onEquals(SimpleSession ss) { return (getStartTimestamp() != null ? getStartTimestamp().equals(ss.getStartTimestamp()) : ss.getStartTimestamp() == null) && (getStopTimestamp() != null ? getStopTimestamp().equals(ss.getStopTimestamp()) : ss.getStopTimestamp() == null) && (getLastAccessTime() != null ? getLastAccessTime().equals(ss.getLastAccessTime()) : ss.getLastAccessTime() == null) && (getTimeout() == ss.getTimeout()) && (isExpired() == ss.isExpired()) && (getHost() != null ? getHost().equals(ss.getHost()) : ss.getHost() == null) && (getAttributes() != null ? getAttributes().equals(ss.getAttributes()) : ss.getAttributes() == null); } /** * Returns the hashCode. If the {@link #getId() id} is not {@code null}, its hashcode is returned immediately. * If it is {@code null}, an attributes-based hashCode will be calculated and returned. *

* Do your best to ensure {@code PersistentSession} instances receive an ID very early in their lifecycle to * avoid the more expensive attributes-based calculation. * * @return this object's hashCode * @since 1.0 */ @Override public int hashCode() { Serializable id = getId(); if (id != null) { return id.hashCode(); } int hashCode = getStartTimestamp() != null ? getStartTimestamp().hashCode() : 0; hashCode = 31 * hashCode + (getStopTimestamp() != null ? getStopTimestamp().hashCode() : 0); hashCode = 31 * hashCode + (getLastAccessTime() != null ? getLastAccessTime().hashCode() : 0); hashCode = 31 * hashCode + Long.valueOf(Math.max(getTimeout(), 0)).hashCode(); hashCode = 31 * hashCode + Boolean.valueOf(isExpired()).hashCode(); hashCode = 31 * hashCode + (getHost() != null ? getHost().hashCode() : 0); hashCode = 31 * hashCode + (getAttributes() != null ? getAttributes().hashCode() : 0); return hashCode; } /** * Returns the string representation of this PersistentSession, equal to * getClass().getName() + ",id=" + getId(). * * @return the string representation of this PersistentSession, equal to * getClass().getName() + ",id=" + getId(). * @since 1.0 */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getName()).append(",id=").append(getId()); return sb.toString(); } }