Maison > Java > javaDidacticiel > le corps du texte

Un exemple d'analyse de Session session = getSession() dans l'apprentissage du code source de Shiro

黄舟
Libérer: 2017-07-24 13:26:51
original
7472 Les gens l'ont consulté

Le sujet représente certaines opérations permettant aux utilisateurs d'accéder au serveur : telles que la connexion, la déconnexion, l'affichage des rôles/autorisations,

En même temps, vous pouvez obtenir la session, par exemple : subject.getSession (), cette connexion, si elle n'existe pas avant la session, crée une session. Le processus de création est à peu près le suivant :

le sujet confie à SecurityManager la création, SecurityManager confie à SessionManager la création et SessionManager est créé via l'usine SessionFactory. On peut voir que le processus de création de Shiro comporte une division claire du travail.

Le processus de création s’analyse comme suit.

(1)La session peut être obtenue dans la classe DelegatingSubject :

public Session getSession(boolean create) {
      .......
      SessionContext sessionContext = createSessionContext();
      //创建Session上下文,context有个backMap,存放创建Session时所需的数据
      Session session = this.securityManager.start(sessionContext);
      this.session = decorate(session);//创建代理session,当session.stop()调用时,清空subject的session
      .......
      return this.session;//返回代理session
 }
Copier après la connexion

(2)SecurityManager confie à sessionManager (DefaultSessionManage) le soin de gérer la création de Session :

1 public Session start(SessionContext context) throws AuthorizationException {
2     return this.sessionManager.start(context);
3     }
Copier après la connexion

* Remarque : La structure interne de DefaultSessionManage est :

(3)AbstractNativeSessionManager crée une session et gère la session :

public Session start(SessionContext context) {
        Session session = createSession(context);//通过模板模式,子类实现通过上下仍创建Session
        applyGlobalSessionTimeout(session);//更新sessionDAO的sessions(map<String,session>)
        onStart(session, context);//一个槽点,待子类实现
        notifyStart(session);//注册的监听器开始执行
        //Don&#39;t expose the EIS-tier Session object to the client-tier:
        return createExposedSession(session, context);//创建暴露的Session
    }
Copier après la connexion

(4)Pour la création de cette session est terminée, et le code détaillé est le suivant : AbstractNativeSessionManager est remis à AbstractValidatingSessionManager pour traitement :

protected Session createSession(SessionContext context) throws AuthorizationException {
        enableSessionValidationIfNecessary();
        //创建Session之前,先起一个Session自动定时任务的线程去执行,校验sessionDAO的sessions是否过期。
        return doCreateSession(context);
    }
//
private void enableSessionValidationIfNecessary() {
        SessionValidationScheduler scheduler = getSessionValidationScheduler();
        if (isSessionValidationSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) {
            enableSessionValidation();
        }
    }
//
protected void enableSessionValidation() {
        SessionValidationScheduler scheduler = getSessionValidationScheduler();
        if (scheduler == null) {
            scheduler = createSessionValidationScheduler();
            //scheduler = new ExecutorServiceSessionValidationScheduler(this);scheduler.setInterval(getSessionValidationInterval());
            setSessionValidationScheduler(scheduler);
        }
        if (log.isInfoEnabled()) {
            log.info("Enabling session validation scheduler...");
        }
        scheduler.enableSessionValidation();//自动任务启动执行
        afterSessionValidationEnabled();//一个槽点,待子类实现
}
Copier après la connexion

(5) ExecutorServiceSessionValidationScheduler vérifie l'expiration de la session :

/**
     * Creates a single thread {@link ScheduledExecutorService} to validate sessions at fixed intervals 
     * and enables this scheduler. The executor is created as a daemon thread to allow JVM to shut down
     */
    //TODO Implement an integration test to test for jvm exit as part of the standalone example
    // (so we don&#39;t have to change the unit test execution model for the core module)
    public void enableSessionValidation() {
        if (this.interval > 0l) {
            this.service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {  
            public Thread newThread(Runnable r) {  
                Thread thread = new Thread(r);  
                thread.setDaemon(true);  
                return thread;  
                }  
            });                  
            this.service.scheduleAtFixedRate(this, interval, interval, TimeUnit.MILLISECONDS);
            this.enabled = true;
        }
    }

    public void run() {
        if (log.isDebugEnabled()) {
            log.debug("Executing session validation...");
        }
        long startTime = System.currentTimeMillis();
        this.sessionManager.validateSessions();//ExecutorServiceSessionValidationSchedule的在被SessionManager创建里,
        long stopTime = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
        }
    }
Copier après la connexion

(6) AbstractValidatingSessionManager vérifie l'expiration de la session :

/**
     * @see ValidatingSessionManager#validateSessions()
     */
    public void validateSessions() {
        if (log.isInfoEnabled()) {
            log.info("Validating all active sessions...");
        }
        int invalidCount = 0;
        Collection<Session> activeSessions = getActiveSessions();//获取取保存的Session
        if (activeSessions != null && !activeSessions.isEmpty()) {
            for (Session s : activeSessions) {
                try {
                    //simulate a lookup key to satisfy the method signature.
                    //this could probably stand to be cleaned up in future versions:
                    SessionKey key = new DefaultSessionKey(s.getId());
                    validate(s, key);
                } catch (InvalidSessionException e) {
                    if (log.isDebugEnabled()) {
                        boolean expired = (e instanceof ExpiredSessionException);
                        String msg = "Invalidated session with id [" + s.getId() + "]" +
                                (expired ? " (expired)" : " (stopped)");
                        log.debug(msg);
                    }
                    invalidCount++;
                }
            }
        }

        if (log.isInfoEnabled()) {
            String msg = "Finished session validation.";
            if (invalidCount > 0) {
                msg += "  [" + invalidCount + "] sessions were stopped.";
            } else {
                msg += "  No sessions were stopped.";
            }
            log.info(msg);
        }
    }
    //类DefaultSessionManager实现getActiveSessions接口
    protected abstract Collection<Session> getActiveSessions();

     protected Collection<Session> getActiveSessions() {
        Collection<Session> active = sessionDAO.getActiveSessions();
        return active != null ? active : Collections.<Session>emptySet();
    }
Copier après la connexion

(7)La vérification de la session est terminée, puis DefaultSessionManager crée la session :

protected Session doCreateSession(SessionContext context) {
        Session s = newSessionInstance(context);
        if (log.isTraceEnabled()) {
            log.trace("Creating session for host {}", s.getHost());
         }
        create(s);
        return s;
     }

   protected Session newSessionInstance(SessionContext context) {
      return getSessionFactory().createSession(context);
   }
   protected void create(Session session) {
      if (log.isDebugEnabled()) {
         log.debug("Creating new EIS record for new session instance [" + session + "]");
        }
      sessionDAO.create(session);
    }
Copier après la connexion

(8)DefaultSessionManager confie Session (MemorySessionDAO) pour maintenir la session :

protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        storeSession(sessionId, session);
        return sessionId;
    }
        protected Session storeSession(Serializable id, Session session) {
          if (id == null) {
             throw new NullPointerException("id argument cannot be null.");
          }
          return sessions.putIfAbsent(id, session);
        }
Copier après la connexion

(9) Après avoir créé et maintenu la session, le AbstractNativeSessionManager est remis à l'auditeur enregistré, et l'auditeur appelle l'interface onStart

  protected void notifyStart(Session session) {
  2         for (SessionListener listener : this.listeners) {
  3             listener.onStart(session);
  4         }
  5     }
Copier après la connexion

(10) Enfin, la Session déléguée est créée,

protected Session createExposedSession(Session session, SessionContext context) {        
return new DelegatingSession(this, new DefaultSessionKey(session.getId()));
    }
Copier après la connexion

(11) Enfin, le Sujet crée sa propre Session proxy, qui sert principalement à intercepter la méthode stop :

protected Session decorate(Session session) {
         if (session == null) {
             throw new IllegalArgumentException("session cannot be null");
         }
         return new StoppingAwareProxiedSession(session, this);
     }
    private class StoppingAwareProxiedSession extends ProxiedSession {

           private final DelegatingSubject owner;

           private StoppingAwareProxiedSession(Session target, DelegatingSubject owningSubject) {
                super(target);
                owner = owningSubject;
            }
16            public void stop() throws InvalidSessionException {
           super.stop();
           owner.sessionStopped();
         }
       }
Copier après la connexion

Résumé : Lorsque la session (SimpleSession) est créée dans DefaultSessionManage, elle est encapsulée dans DelegatingSession , et est décorée comme une session proxy (StoppingAwareProxiedSession) dans le sujet. Les données d'origine sont bien enregistrées, afin que le client ne puisse pas. modifier la Session originale à volonté

...


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal