Shiro-about session

Source: Internet
Author: User

Shiro Session

Session management can be said to be a major selling point of Shiro.
Shiro can provide a session solution for any application, from simple command-line programs to mobile apps to large enterprise applications.
Before Shiro appears, if we want your app to support the session, we will usually rely on the Web container or the session Bean that uses the EJB.
Shiro's support for sessions is more user-friendly and can be used in any application, any container.
Even if we use Servlets or EJBS, it does not mean that we have to use the Session,shiro of the container to provide some of the features that allow us to replace them with the Shiro session.

    • Based on Pojo
    • Easy Customization Session Persistence
    • Container-independent Session cluster
    • Supports multiple Client access
    • Session Event Listener
    • Extension of the failed session
    • Transparent support for the web
    • Support SSO

When using the Shiro session, the methods are the same both in the Javase and the Web.

public static void main(String[] args) {    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro/shiro.ini");    SecurityUtils.setSecurityManager(factory.getInstance());    Subject currentUser = SecurityUtils.getSubject();    UsernamePasswordToken token = new UsernamePasswordToken("king","t;stmdtkg");    currentUser.login(token);    Session session = currentUser.getSession();    System.out.println(session.getHost());    System.out.println(session.getId());    System.out.println(session.getStartTimestamp());    System.out.println(session.getLastAccessTime());    session.touch();    User u = new User();     session.setAttribute(u, "King.");    Iterator<Object> keyItr = session.getAttributeKeys().iterator();    while(keyItr.hasNext()){        System.out.println(session.getAttribute(keyItr.next()));    }}


No matter what the environment, just call subject's getsession ().
In addition, subject also offers a ...

Session getSession(boolean create);

That is, if the current subject session does not exist, the new session is created and returned.

Take Delegatingsubject as an example:
(Note: Starting from Shiro 1.2, there is a issessioncreationenabled property with a default value of True. )

Public Session getsession () {return getsession (true);} Public Session getsession (Boolean Create) {if (log.istraceenabled ()) {Log.trace ("attempting to get Session; Create = "+ Create +"; Session is NULL = "+ (this.session = = null) +";    Session has ID = "+ (this.session! = null && session.getid () = null));            } if (this.session = = NULL && create) {//added in 1.2:if (!issessioncreationenabled ()) {  String msg = "Session creation have been disabled for the current subject. This exception indicates "+" that there was either a programming error (using a session when it should Never is "+" used) or that Shiro's configuration needs to being adjusted to allow Sessions to be created  "+" for the current Subject.            See the "+ DisabledSessionException.class.getName () +" JavaDoc "+" for more. "; throw new DisabledsessionException (msg);        } log.trace ("Starting session for host {}", GetHost ());        Sessioncontext Sessioncontext = Createsessioncontext ();        Session session = This.securityManager.start (Sessioncontext);    This.session = decorate (session); } return this.session;}

SessionManager

As its name, SessionManager is used to manage sessions for subject in the application, such as creation, deletion, invalidation, or validation.
Like other core components in Shiro, he is maintained by SecurityManager.
(Note: public interface SecurityManager extends Authenticator, Authorizer, SessionManager).

public interface SessionManager {    Session start(SessionContext context);    Session getSession(SessionKey key) throws SessionException;}


Shiro provides 3 implementation classes for SessionManager (and, by the way, a relationship with the SecurityManager implementation Class).

    • Defaultsessionmanager
    • Defaultwebsessionmanager
    • Servletcontainersessionmanager

Where Servletcontainersessionmanager is only available in servlet containers, you should use Defaultwebsessionmanager if you need to support multiple client access.

By default, the time-out of the SessionManager implementation class is set to 30 minutes.
See Abstractsessionmanager:

public static final long DEFAULT_GLOBAL_SESSION_TIMEOUT = 30 * MILLIS_PER_MINUTE;private long globalSessionTimeout = DEFAULT_GLOBAL_SESSION_TIMEOUT;


Of course, we can also directly set Abstractsessionmanager's globalsessiontimeout.
For example, in the. INI:

securityManager.sessionManager.globalSessionTimeout = 3600000


Attention! If the SessionManager used is Servletcontainersessionmanager (no inheritance abstractsessionmanager), the timeout setting relies on the settings of the servlet container.
See: https://issues.apache.org/jira/browse/SHIRO-240
The validation method for session expiration can refer to Simplesession:

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 is set at "+" least once, preferably at least upon instantiation. Please check the "+ GetClass (). GetName () +" implementation and ensure "+" this VA            Lue'll is set (perhaps in the constructor?) ";        throw new IllegalStateException (msg);  }//Calculate at "What time a session would" has been last accessed//for it to being expired at this point. In other words, subtract//from the current time the amount of time a session can//be inactive befo  Re 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;}


Try detect from Securityutils.getsubject () and feel how the session is set to subject.
After judging if there is subject in the thread context, if it does not exist, we use subject's internal class builder for Buildsubject ();

public static Subject getSubject() {    Subject subject = ThreadContext.getSubject();    if (subject == null) {        subject = (new Subject.Builder()).buildSubject();        ThreadContext.bind(subject);    }    return subject;}


Buildsubject () delegate the work of establishing subject to securitymanager.createsubject (Subjectcontext)
Createsubject will call Resolvesession to process the session.

  protected Subjectcontext resolvesession (Subjectcontext context) {if (context.resolvesession ()! = null) {  Log.debug ("Context already contains a session.        Returning. ");    return context;  } try {//context couldn ' t resolve it directly, let's see if we can since we had direct access to//the        Session Manager:session Session = Resolvecontextsession (context);        if (session! = NULL) {context.setsession (session);  }} catch (Invalidsessionexception e) {log.debug ("resolved Subjectcontext context session is invalid.    Ignoring and creating an anonymous "+" (session-less) Subject instance. ", e); } return context;}  


Resolvesession (Subjectcontext), first attempts to get the session from the context (Mapcontext), and if it cannot be obtained directly, it acquires subject and then calls its getsession (false).
Call Resolvecontextsession (Subjectcontext) If it still does not exist, try to get SessionID from Mapcontext, instantiate a SessionID object according to SessionKey, and get the session through the SessionKey instance.
The task of getsession (key) is given directly to SessionManager for execution.

public Session getSession(SessionKey key) throws SessionException {    return this.sessionManager.getSession(key);}


The Sessionmanager.getsession (key) method is defined in Abstractnativesessionmanager and the method calls Lookupsession (key), Lookupsession calls Dogetsession (key), Dogetsession (key) is a protected abstract that implements the subclass Abstractvalidatingsessionmanager Supply ( Final).
Dogetsession calls Retrievesession (key), which attempts to get session information through Sessiondao.
Finally, determine if the session is empty and validate it (refer to Simplesession.validate ()).

protected final Session doGetSession(final SessionKey key) throws InvalidSessionException {    enableSessionValidationIfNecessary();    log.trace("Attempting to retrieve session with key {}", key);    Session s = retrieveSession(key);    if (s != null) {        validate(s, key);    }    return s;}

Session Listener

We can monitor the session via Sessionlistener interface or Sessionlisteneradapter, and operate on demand when the session is created, stopped, and expires.

public interface SessionListener {    void onStart(Session session);    void onStop(Session session);    void onExpiration(Session session);}


I just need to define a listener and inject it into the sessionmanager.

Package Pac.testcase.shiro.listener;import Org.apache.shiro.session.session;import Org.apache.shiro.session.sessionlistener;public class Mysessionlistener implements Sessionlistener {public void OnSta    RT (Session session) {SYSTEM.OUT.PRINTLN (Session.getid () + "start ...");    } public void OnStop (session session) {SYSTEM.OUT.PRINTLN (Session.getid () + "Stop ...");    } public void Onexpiration (session session) {SYSTEM.OUT.PRINTLN (Session.getid () + "expired ..."); }}[main]realm0=pac.testcase.shiro.realm.myrealm0realm1=pac.testcase.shiro.realm.myrealm1authcstrategy = Org.apache.shiro.authc.pam.AllSuccessfulStrategysessionManager = Org.apache.shiro.web.session.mgt.defaultwebsessionmanager#sessionmanager = Org.apache.shiro.web.session.mgt.ServletContainerSessionManagersessionListener = pac.testcase.shiro.listener.mysessionlistenersecuritymanager.realms=$ Realm1securityManager.authenticator.authenticationStrategy = $authcStrategysecurityManager. sessionmanager= $sesSionmanager#sessionmanager.sessionlisteners = $sessionListener securitymanager.sessionmanager.sessionlisteners=$ Sessionlistener

Sessiondao

SessionManager delegate the work of the session crud to Sessiondao.
We can implement Sessiondao with a specific data source API to store the session in any data source.

public interface SessionDAO {    Serializable create(Session session);    Session readSession(Serializable sessionId) throws UnknownSessionException;    void update(Session session) throws UnknownSessionException;    void delete(Session session);    Collection<Session> getActiveSessions();}


Of course, you can use the same class to take the past.

    • Abstractsessiondao: During create and read, the session is validated to ensure that the session is available, and the SessionID generation method is provided.
    • Cachingsessiondao: Provides transparent cache support for session storage and maintains the cache using CacheManager.
    • Enterprisecachesessiondao: Abstractcachemanager Createcache is overridden by an anonymous inner class, returning the MapCache object.
    • Memorysessiondao: A memory-based implementation in which all sessions are placed in memory.

The anonymous inner class in the Enterprisecachesessiondao is the CacheManager.

Use Memorysessiondao by default (note!) Defaultwebsessionmanager extends Defaultsessionmanager)

Of course, we can also try to use the cache.
Shiro does not enable Ehcache by default, but in order to ensure that the session is not somehow lost at runtime, it is recommended to enable Ehcache to optimize session management.
Enabling Ehcache for the session persistence service is very simple, first we need to add a denpendency.

<dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-ehcache</artifactId>    <version>${shiro.version}</version></dependency>


Then you just need to configure it as an example of. ini configuration:

  [Main]realm0=pac.testcase.shiro.realm.myrealm0realm1=pac.testcase.shiro.realm.myrealm1authcstrategy = Org.apache.shiro.authc.pam.AllSuccessfulStrategysessionManager = Org.apache.shiro.web.session.mgt.defaultwebsessionmanagercachemanager= org.apache.shiro.cache.ehcache.ehcachemanagersessiondao= Org.apache.shiro.session.mgt.eis.enterprisecachesessiondao#sessionmanager = Org.apache.shiro.web.session.mgt.ServletContainerSessionManagersessionListener = pac.testcase.shiro.listener.mysessionlistenersecuritymanager.realms=$ Realm1securityManager.authenticator.authenticationStrategy = $authcStrategysecurityManager. sessionmanager=$  Sessionmanagersessionmanager.sessionlisteners = $sessionListenersessionDAO. cachemanager= $cacheManager securitymanager.sessionmanager.sessiondao= $sessionDAOsecurityManager. sessionmanager.sessionlisteners=$ Sessionlistener  

Here is primarily the definition and reference of CacheManager.
In addition, the Sessiondao used here is Enterprisecachesessiondao.
As mentioned earlier, the CacheManager used by Enterprisecachesessiondao is based on MapCache.
In fact this setting does not affect because Enterprisecachesessiondao inherits Cachingsessiondao,cachingsessiondao implementation Cachemanageraware.

Attention! The Sessiondao property is only available when using the SessionManager implementation class.
(In fact they have defined Sessiondao in Defaultsessionmanager, but there seems to be a plan to put Sessiondao in Abstractvalidatingsessionmanager. )
If you configure Shiro in your Web app, you'll be surprised to see that Securitymanger's SessionManager property is Servletcontainersessionmanager.
Look at the above hierarchy to find that Servletcontainersessionmanager and Defaultsessionmanager are not related.
That is, Servletcontainersessionmanager does not support Sessiondao (the Cachemanger attribute is defined in Cachingsessiondao).
You need to display the specified SessionManager as Defaultwebsessionmanager at this time.

With regard to the configuration of Ehcache, by default Ehcachemanager uses the specified configuration file, which is:

private String cacheManagerConfigFile = "classpath:org/apache/shiro/cache/ehcache/ehcache.xml";


Take a look at his configuration:

<ehcache>    <diskStore path="java.io.tmpdir/shiro-ehcache"/>    <defaultCache            maxElementsInMemory="10000"            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            overflowToDisk="false"            diskPersistent="false"            diskExpiryThreadIntervalSeconds="120"            />    <cache name="shiro-activeSessionCache"           maxElementsInMemory="10000"           overflowToDisk="true"           eternal="true"           timeToLiveSeconds="0"           timeToIdleSeconds="0"           diskPersistent="true"           diskExpiryThreadIntervalSeconds="600"/>    <cache name="org.apache.shiro.realm.text.PropertiesRealm-0-accounts"           maxElementsInMemory="1000"           eternal="true"           overflowToDisk="true"/></ehcache>

If you intend to change the original setting, there are two attributes that require special attention:

    • Overflowtodisk= "true": ensure that the session is not lost.
    • Eternal= "true": ensure that the session cache is not automatically invalidated, and that setting it to false may not match the logic of the session validation.

      In addition, name uses "Shiro-activesessioncache" by default

      public static final String ACTIVESESSIONcache_name = "Shiro-activesessioncache";

If you intend to use a different name, simply set activesessionscachename in Cachingsessiondao or its subclasses.

When a new session is created, the Sessiondao implementation class uses Sessionidgenerator to generate an ID for the session.
The default use of Sessionidgenerator is Javauuidsessionidgenerator, which is now:

public Serializable generateId(Session session) {    return UUID.randomUUID().toString();}

Of course, we can also customize the implementation of Sessionidgenerator.

Session Validation & Scheduling

For example, when a user uses a web app on a browser, the session is created and cached, but the user can simply switch off the browser, power off, blackout, or other natural disasters when exiting. Then the state of the session is unknown (it is orphaned).
To prevent the rubbish from being piled up a little bit, we need to periodically check the session and delete the session if necessary.
So we have Sessionvalidationscheduler:

public interface SessionValidationScheduler {    boolean isEnabled();    void enableSessionValidation();    void disableSessionValidation();}

Shiro only provides an implementation, Executorservicesessionvalidationscheduler. By default, the validation cycle is 60 minutes. Of course, we can also change the validation period (in milliseconds) by modifying his interval property, for example:

sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationSchedulersessionValidationScheduler.interval = 3600000securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler


If you intend to disable the cycle-by-period validation session (for example, if we do some work outside of Shiro), you can set

securityManager.sessionManager.sessionValidationSchedulerEnabled = false


If you do not want to delete the invalid session (for example, we want to do some statistics, etc.), you can set

securityManager.sessionManager.deleteInvalidSessions = false

Shiro-about session

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.