2.详解SecurityManager(shiro权限管理门面)

来源:互联网 发布:土木工程领域大数据 编辑:程序博客网 时间:2024/05/22 00:27

SecurityManager 接口主要作用
为什么要先说SecurityManager呢?因为我觉得他是shiro的主要入口,几乎所有相关的权限操作,都由他代理了。
1.可以说是所有配置的入口,简化配置,方便使用。
2.一个接口就可以实现,验证的操作(登录、退出)、授权(授权访问指定资源、角色)、Session管理,相当于这些操作的门面(门面模式,也叫外观模式)。

这里写图片描述

从上图我们可以看出SecurityManager各个子类的作用及子类的依赖组件的接口。下面我们底层子类往上推,分别详解各个子类的作用
1. CachingSecurityManager

//该抽象类实现类CacheManagerAware 接口,主要提供缓存支持,管理缓存操作public abstract class CachingSecurityManager implements SecurityManager, Destroyable, CacheManagerAware {    //缓存接口的实现类,实现可以是ehcache,java的HashMap版的cacheManager,redis    private CacheManager cacheManager;    //通过该接口可以获取cacheManager,然后使用它来做一些你所需的操作,如进行一些自定义的缓存管理    public CacheManager getCacheManager() {        return cacheManager;    }    public void setCacheManager(CacheManager cacheManager) {        this.cacheManager = cacheManager;        //在设置cacheManager后,执行一些后续操作。该后续操作主要是:设置cacheManagr到Realm和SessionManager等相关依cacheManagr的类        afterCacheManagerSet();    }    //Template 方法,让子类重写实现业务逻辑    protected void afterCacheManagerSet() {    }    //销毁SecurityManager时,销毁该缓存实例    public void destroy() {        LifecycleUtils.destroy(getCacheManager());        this.cacheManager = null;    }}

2.RealmSecurityManager

//该抽象类主要是管理Realm(可以理解为数据处理组件,比如Realm根据用户名查找底层数据库,然后取出来和你输入的用户密码进行批评,验证是否equals来验证是否登陆成功,还有授权数据等)public abstract class RealmSecurityManager extends CachingSecurityManager {    //至少需要一个Realm,可以是多个。相当于多个数据处理中心,比如mysql数据库,redis数据库    private Collection<Realm> realms;    public void setRealm(Realm realm) {        if (realm == null) {            throw new IllegalArgumentException("Realm argument cannot be null");        }        Collection<Realm> realms = new ArrayList<Realm>(1);        realms.add(realm);        setRealms(realms);    }    public void setRealms(Collection<Realm> realms) {        if (realms == null) {            throw new IllegalArgumentException("Realms collection argument cannot be null.");        }        if (realms.isEmpty()) {            throw new IllegalArgumentException("Realms collection argument cannot be empty.");        }        this.realms = realms;        //模板方法,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中        afterRealmsSet();    }    protected void afterRealmsSet() {        applyCacheManagerToRealms();    }    //获取realm,根据你是否有需求来决定使用。可能应用场景:从Realm中获取用户的授权、验证的缓存信息    public Collection<Realm> getRealms() {        return realms;    }   //设置cacheManager到Realm中,因为Realm是数据处理组件,当它从数据库中加载数据且得到正确的验证后,可以缓存到cacheManager,来提供性能。在shiro里,AuthorizationInfo(授权数据)和AuthenticationInfo(用户基本账户密码)都被缓存到cacheManager在验证成功后    protected void applyCacheManagerToRealms() {        CacheManager cacheManager = getCacheManager();        Collection<Realm> realms = getRealms();        if (cacheManager != null && realms != null && !realms.isEmpty()) {            for (Realm realm : realms) {                if (realm instanceof CacheManagerAware) {                    ((CacheManagerAware) realm).setCacheManager(cacheManager);                }            }        }    }    protected void afterCacheManagerSet() {        applyCacheManagerToRealms();    }    //销毁realms    public void destroy() {        LifecycleUtils.destroy(getRealms());        this.realms = null;        super.destroy();    }}

3.AuthenticatingSecurityManager

//实现接口Authenticator,处理用户登陆验证的 SecurityManager 的 抽象实现,仅仅代理Authenticator.public abstract class AuthenticatingSecurityManager extends RealmSecurityManager {    //依赖authenticator验证器,真正的登陆验证都在这里面处理    private Authenticator authenticator;    public AuthenticatingSecurityManager() {        super();    //默认的Authenticator,在大多数情况下,该默认实例足够用了        this.authenticator = new ModularRealmAuthenticator();    }    public Authenticator getAuthenticator() {        return authenticator;    }    //覆盖默认的ModularRealmAuthenticator    public void setAuthenticator(Authenticator authenticator) throws IllegalArgumentException {        if (authenticator == null) {            String msg = "Authenticator argument cannot be null.";            throw new IllegalArgumentException(msg);        }        this.authenticator = authenticator;    }    //重写父类模板方法    protected void afterRealmsSet() {        super.afterRealmsSet();        if (this.authenticator instanceof ModularRealmAuthenticator) {            ((ModularRealmAuthenticator) this.authenticator).setRealms(getRealms());        }    }    //该类的核心,调用底层的authenticator进行用户输入的账户密码验证    //token 是用户输入的账户密码    public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {        return this.authenticator.authenticate(token);    }    //销毁Authenticator    public void destroy() {        LifecycleUtils.destroy(getAuthenticator());        this.authenticator = null;        super.destroy();    }}

4.AuthorizingSecurityManager

//AuthorizingSecurityManager是实现了Authorizer接口的抽象类,该类主要代理Authorizer进行授权。public abstract class AuthorizingSecurityManager extends AuthenticatingSecurityManager {    //真正的授权器    private Authorizer authorizer;    public AuthorizingSecurityManager() {        super();    //默认的Authorizer,该默认实例支持大部分使用场景        this.authorizer = new ModularRealmAuthorizer();    }    public Authorizer getAuthorizer() {        return authorizer;    }    //覆盖默认的Authorizer    public void setAuthorizer(Authorizer authorizer) {        if (authorizer == null) {            String msg = "Authorizer argument cannot be null.";            throw new IllegalArgumentException(msg);        }        this.authorizer = authorizer;    }    //重写父类的afterRealmsSet(),首先调用父类的afterRealmsSet(),然后在设置realms到授权器,如果实现是ModularRealmAuthorizer。也就是说如果你覆盖了默认的    ModularRealmAuthorizer,那么你要对这个方法进行处理。    protected void afterRealmsSet() {        super.afterRealmsSet();        if (this.authorizer instanceof ModularRealmAuthorizer) {            ((ModularRealmAuthorizer) this.authorizer).setRealms(getRealms());        }    }    public void destroy() {        LifecycleUtils.destroy(getAuthorizer());        this.authorizer = null;        super.destroy();    }    /**    以下都是调用底层的authorizer来进行授权处理。所有的用户是否能授权其实就是调用以下方法。后面详讲authorizer,会讲解每个方法的意思,大家可以随便看看有个影像就可以了。    总的来说就两类:一类是返回true false来说明是否授权成功,一个抛异常来说明是否授权成功    **/    public boolean isPermitted(PrincipalCollection principals, String permissionString) {        return this.authorizer.isPermitted(principals, permissionString);    }    public boolean isPermitted(PrincipalCollection principals, Permission permission) {        return this.authorizer.isPermitted(principals, permission);    }    public boolean[] isPermitted(PrincipalCollection principals, String... permissions) {        return this.authorizer.isPermitted(principals, permissions);    }    public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) {        return this.authorizer.isPermitted(principals, permissions);    }    public boolean isPermittedAll(PrincipalCollection principals, String... permissions) {        return this.authorizer.isPermittedAll(principals, permissions);    }    public boolean isPermittedAll(PrincipalCollection principals, Collection<Permission> permissions) {        return this.authorizer.isPermittedAll(principals, permissions);    }    public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException {        this.authorizer.checkPermission(principals, permission);    }    public void checkPermission(PrincipalCollection principals, Permission permission) throws AuthorizationException {        this.authorizer.checkPermission(principals, permission);    }    public void checkPermissions(PrincipalCollection principals, String... permissions) throws AuthorizationException {        this.authorizer.checkPermissions(principals, permissions);    }    public void checkPermissions(PrincipalCollection principals, Collection<Permission> permissions) throws AuthorizationException {        this.authorizer.checkPermissions(principals, permissions);    }    public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {        return this.authorizer.hasRole(principals, roleIdentifier);    }    public boolean[] hasRoles(PrincipalCollection principals, List<String> roleIdentifiers) {        return this.authorizer.hasRoles(principals, roleIdentifiers);    }    public boolean hasAllRoles(PrincipalCollection principals, Collection<String> roleIdentifiers) {        return this.authorizer.hasAllRoles(principals, roleIdentifiers);    }    public void checkRole(PrincipalCollection principals, String role) throws AuthorizationException {        this.authorizer.checkRole(principals, role);    }    public void checkRoles(PrincipalCollection principals, Collection<String> roles) throws AuthorizationException {        this.authorizer.checkRoles(principals, roles);    }    public void checkRoles(PrincipalCollection principals, String... roles) throws AuthorizationException {        this.authorizer.checkRoles(principals, roles);    }    }

5.SessionsSecurityManager

//SessionsSecurityManager实现类SessionManager的方法。代理了SessionManager来处理相关的session操作。public abstract class SessionsSecurityManager extends AuthorizingSecurityManager {    //Session管理    private SessionManager sessionManager;    public SessionsSecurityManager() {        super();    //默认的SessionManager的实现类        this.sessionManager = new DefaultSessionManager();    //顾名思义,设置CacheManager到sessionManager        applyCacheManagerToSessionManager();    }     public void setSessionManager(SessionManager sessionManager) {        this.sessionManager = sessionManager;        afterSessionManagerSet();    }    //在sessionManager被设置后调用,该类只调用 applyCacheManagerToSessionManager(),大家可以琢磨下这样写的好处,子类可以重写增强等    protected void afterSessionManagerSet() {        applyCacheManagerToSessionManager();    }    //获取sessionManager,根据你的需求。除了下面的方法,可能使用场景:获取所有在线session    public SessionManager getSessionManager() {        return this.sessionManager;    }    //增强父类的afterCacheManagerSet(),满足本类需求    protected void afterCacheManagerSet() {        super.afterCacheManagerSet();        applyCacheManagerToSessionManager();    }    //如果sessionManager实现了CacheManagerAware,则设置cacheManager    protected void applyCacheManagerToSessionManager() {        if (this.sessionManager instanceof CacheManagerAware) {            ((CacheManagerAware) this.sessionManager).setCacheManager(getCacheManager());        }    }    //调用sessionManager根据上下文context(存储session的相关创建信息,大家可以去了解下上下文)创建个session    public Session start(SessionContext context) throws AuthorizationException {        return this.sessionManager.start(context);    }    //根据sessionID来获取session,每次生成session后会生成个sessionID返回给浏览器,浏览器用sessionID来和sessionManager进行交互    public Session getSession(SessionKey key) throws SessionException {        return this.sessionManager.getSession(key);    }    //销毁sessionManager    public void destroy() {        LifecycleUtils.destroy(getSessionManager());        this.sessionManager = null;        super.destroy();    }}

6.DefaultSecurityManager

//默认的SessionManager的具体实现,该实现类会合适的初始化依赖组件。如subjectFactory、SubjectDAOpublic class DefaultSecurityManager extends SessionsSecurityManager {    private static final Logger log = LoggerFactory.getLogger(DefaultSecurityManager.class);    //是否记住密码服务组件    protected RememberMeManager rememberMeManager;    //subject(代理特定的一个用户的所有权限相关操作,登陆退出、授权,获取session等)的管理组件,仅提供了save和delete方法。用于保存subject的状态,方便与以后可以重建subject    protected SubjectDAO subjectDAO;    //根据SubjectContext(subject的状态和相关的数据)来创建个subject    protected SubjectFactory subjectFactory;    public DefaultSecurityManager() {        super();        this.subjectFactory = new DefaultSubjectFactory();        this.subjectDAO = new DefaultSubjectDAO();    }    public DefaultSecurityManager(Realm singleRealm) {        this();        setRealm(singleRealm);    }    //realms 调用子类的 setRealms(realms),至少需要一个。    public DefaultSecurityManager(Collection<Realm> realms) {        this();        setRealms(realms);    }    //获取subjectFactory,主要用于创建subject    public SubjectFactory getSubjectFactory() {        return subjectFactory;    }    public void setSubjectFactory(SubjectFactory subjectFactory) {        this.subjectFactory = subjectFactory;    }    //获取subjectDAO,主要用于持久化或者删除subject状态(该状态可用于以后来重建subject)    public SubjectDAO getSubjectDAO() {        return subjectDAO;    }    public void setSubjectDAO(SubjectDAO subjectDAO) {        this.subjectDAO = subjectDAO;    }    public RememberMeManager getRememberMeManager() {        return rememberMeManager;    }    public void setRememberMeManager(RememberMeManager rememberMeManager) {        this.rememberMeManager = rememberMeManager;    }    protected SubjectContext createSubjectContext() {        return new DefaultSubjectContext();    }    //根据形参,创建个subject。    //token用户输入的账户密码,info从数据库加载的账户密码    protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing) {    //创建默认的SubjectContext的实现        SubjectContext context = createSubjectContext();    //设置context的是否验证、token和info,方便以后调用        context.setAuthenticated(true);        context.setAuthenticationToken(token);        context.setAuthenticationInfo(info);        if (existing != null) {            context.setSubject(existing);        }        return createSubject(context);    }    //shiri1.2之后已被弃用    @Deprecated    protected void bind(Subject subject) {        save(subject);    }    //执行RememberMeManager的onSuccessfulLogin(subject, token, info)    protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) {        RememberMeManager rmm = getRememberMeManager();        if (rmm != null) {            try {        //记住当前subject, principals                rmm.onSuccessfulLogin(subject, token, info);            } catch (Exception e) {                if (log.isWarnEnabled()) {                    String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +                            "] threw an exception during onSuccessfulLogin.  RememberMe services will not be " +                            "performed for account [" + info + "].";                    log.warn(msg, e);                }            }        } else {            if (log.isTraceEnabled()) {                log.trace("This " + getClass().getName() + " instance does not have a " +                        "[" + RememberMeManager.class.getName() + "] instance configured.  RememberMe services " +                        "will not be performed for account [" + info + "].");            }        }    }    protected void rememberMeFailedLogin(AuthenticationToken token, AuthenticationException ex, Subject subject) {        RememberMeManager rmm = getRememberMeManager();        if (rmm != null) {            try {            //清除cookie(重置cookie为默认值)                rmm.onFailedLogin(subject, token, ex);            } catch (Exception e) {                if (log.isWarnEnabled()) {                    String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +                            "] threw an exception during onFailedLogin for AuthenticationToken [" +                            token + "].";                    log.warn(msg, e);                }            }        }    }    protected void rememberMeLogout(Subject subject) {        RememberMeManager rmm = getRememberMeManager();        if (rmm != null) {            try {        //清除cookie(重置cookie为默认值)                rmm.onLogout(subject);            } catch (Exception e) {                if (log.isWarnEnabled()) {                    String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +                            "] threw an exception during onLogout for subject with principals [" +                            (subject != null ? subject.getPrincipals() : null) + "]";                    log.warn(msg, e);                }            }        }    }    /**    用户登陆验证方法    1.首先调用authenticate(token)验证当前用户登陆信息;    2.登陆验证成功后,创建当前用户的subject且绑定到当前线程和把subject的状态信息保存到session中,方便以后重建subject    **/    public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {        AuthenticationInfo info;        try {        //调用父类AuthenticationSecurityManager的authenticate方法,验证用户是否登陆成功            info = authenticate(token);        } catch (AuthenticationException ae) {            try {            //如果验证失败,重置cookie为初始化值                onFailedLogin(token, ae, subject);            } catch (Exception e) {                if (log.isInfoEnabled()) {                    log.info("onFailedLogin method threw an " +                            "exception.  Logging and propagating original AuthenticationException.", e);                }            }        //验证失败,则抛出异常            throw ae; //propagate        }        //创建subject        Subject loggedIn = createSubject(token, info, subject);    //设置唯一的principle到cookie中        onSuccessfulLogin(token, info, loggedIn);        return loggedIn;    }    protected void onSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) {        rememberMeSuccessfulLogin(token, info, subject);    }    protected void onFailedLogin(AuthenticationToken token, AuthenticationException ae, Subject subject) {        rememberMeFailedLogin(token, ae, subject);    }    protected void beforeLogout(Subject subject) {        rememberMeLogout(subject);    }    protected SubjectContext copy(SubjectContext subjectContext) {        return new DefaultSubjectContext(subjectContext);    }    public Subject createSubject(SubjectContext subjectContext) {        //复制个subjectContext,不修改原来的subjectContext        SubjectContext context = copy(subjectContext);        //确保context已设置securityManager        context = ensureSecurityManager(context);        //确保context已设置session,如果不存在想办法获取已存在的session,然后设置进去        context = resolveSession(context);        //确保context已设置Principals,如果未设置则从rememberManager获取,然后设置        context = resolvePrincipals(context);    //调用subjectFactory创建subject        Subject subject = doCreateSubject(context);        //保存subject状态到session        save(subject);        return subject;    }    protected Subject doCreateSubject(SubjectContext context) {        return getSubjectFactory().createSubject(context);    }    //调用subjectDAO保存subject状态    protected void save(Subject subject) {        this.subjectDAO.save(subject);    }    //调用subjectDAO删除subject状态    protected void delete(Subject subject) {        this.subjectDAO.delete(subject);    }    @SuppressWarnings({"unchecked"})    protected SubjectContext ensureSecurityManager(SubjectContext context) {        if (context.resolveSecurityManager() != null) {            log.trace("Context already contains a SecurityManager instance.  Returning.");            return context;        }        log.trace("No SecurityManager found in context.  Adding self reference.");        context.setSecurityManager(this);        return context;    }    //确保session被设置到context    @SuppressWarnings({"unchecked"})    protected SubjectContext resolveSession(SubjectContext context) {    //如果已经存在session,则直接返回context        if (context.resolveSession() != null) {            log.debug("Context already contains a session.  Returning.");            return context;        }        try {        //根据sessionKey从sessionManager获取session            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;    }    //根据sessionKey从sessionManager获取session    protected Session resolveContextSession(SubjectContext context) throws InvalidSessionException {        SessionKey key = getSessionKey(context);        if (key != null) {            return getSession(key);        }        return null;    }    //获取sessionKey(SID)    protected SessionKey getSessionKey(SubjectContext context) {        Serializable sessionId = context.getSessionId();        if (sessionId != null) {            return new DefaultSessionKey(sessionId);        }        return null;    }    @SuppressWarnings({"unchecked"})    protected SubjectContext resolvePrincipals(SubjectContext context) {        PrincipalCollection principals = context.resolvePrincipals();        if (CollectionUtils.isEmpty(principals)) {        //从Remembered获取principals            principals = getRememberedIdentity(context);            if (!CollectionUtils.isEmpty(principals)) {                context.setPrincipals(principals);            } else {                log.trace("No remembered identity found.  Returning original context.");            }        }        return context;    }    protected SessionContext createSessionContext(SubjectContext subjectContext) {        DefaultSessionContext sessionContext = new DefaultSessionContext();        if (!CollectionUtils.isEmpty(subjectContext)) {            sessionContext.putAll(subjectContext);        }        Serializable sessionId = subjectContext.getSessionId();        if (sessionId != null) {            sessionContext.setSessionId(sessionId);        }        String host = subjectContext.resolveHost();        if (host != null) {            sessionContext.setHost(host);        }        return sessionContext;    }    //用户退出方法    public void logout(Subject subject) {        if (subject == null) {            throw new IllegalArgumentException("Subject method argument cannot be null.");        }    //在执行退出方法前,重置cookie为初始化值        beforeLogout(subject);        PrincipalCollection principals = subject.getPrincipals();        if (principals != null && !principals.isEmpty()) {            if (log.isDebugEnabled()) {                log.debug("Logging out subject with primary principal {}", principals.getPrimaryPrincipal());            }        //调用验证器的onLogout方法,目前该方法主要是迭代AuthenticationListener的logout方法            Authenticator authc = getAuthenticator();            if (authc instanceof LogoutAware) {                ((LogoutAware) authc).onLogout(principals);            }        }        try {            delete(subject);        } catch (Exception e) {        } finally {            try {        //设置session过期                stopSession(subject);            } catch (Exception e) {            }        }    }     //设置session过期    protected void stopSession(Subject subject) {        Session s = subject.getSession(false);        if (s != null) {            s.stop();        }    }    /**     * Unbinds or removes the Subject's state from the application, typically called during {@link #logout}.     * <p/>     * This has been deprecated in Shiro 1.2 in favor of the {@link #delete(org.apache.shiro.subject.Subject) delete}     * method.  The implementation has been updated to invoke that method.     *     * @param subject the subject to unbind from the application as it will no longer be used.     * @deprecated in Shiro 1.2 in favor of {@link #delete(org.apache.shiro.subject.Subject)}     */    @Deprecated    @SuppressWarnings({"UnusedDeclaration"})    protected void unbind(Subject subject) {        delete(subject);    }    //根据SubjectContext从RememberMeManager获取PrincipalCollection    protected PrincipalCollection getRememberedIdentity(SubjectContext subjectContext) {        RememberMeManager rmm = getRememberMeManager();        if (rmm != null) {            try {                return rmm.getRememberedPrincipals(subjectContext);            } catch (Exception e) {                if (log.isWarnEnabled()) {                    String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +                            "] threw an exception during getRememberedPrincipals().";                    log.warn(msg, e);                }            }        }        return null;    }}

7.DefaultWebSecurityManager

//WebSecurityManager实现被使用在基于web的应用程序中或者需要http请求的应用程序中(如SOAP,http remoting, etc)public class DefaultWebSecurityManager extends DefaultSecurityManager implements WebSecurityManager {    private static final Logger log = LoggerFactory.getLogger(DefaultWebSecurityManager.class);    @Deprecated    public static final String HTTP_SESSION_MODE = "http";    @Deprecated    public static final String NATIVE_SESSION_MODE = "native";    /**     * @deprecated as of 1.2.  This should NOT be used for anything other than determining if the sessionMode has changed.     */    @Deprecated    private String sessionMode;    public DefaultWebSecurityManager() {        super();    //设置SessionStorageEvaluator(评估Session是否需要存储,在无状态环境下可以设置为false,如Rest架构)到DefaultSubjectDAO        ((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());        this.sessionMode = HTTP_SESSION_MODE;    //初始化基于WEB的DefaultWebSubjectFactory        setSubjectFactory(new DefaultWebSubjectFactory());        setRememberMeManager(new CookieRememberMeManager());    //默认是 基于servlet的session的sessionManaer,即不使用shiro自己管理的session        setSessionManager(new ServletContainerSessionManager());    }    @SuppressWarnings({"UnusedDeclaration"})    public DefaultWebSecurityManager(Realm singleRealm) {        this();        setRealm(singleRealm);    }    @SuppressWarnings({"UnusedDeclaration"})    public DefaultWebSecurityManager(Collection<Realm> realms) {        this();        setRealms(realms);    }    @Override    protected SubjectContext createSubjectContext() {        return new DefaultWebSubjectContext();    }    @Override    //since 1.2.1 for fixing SHIRO-350    public void setSubjectDAO(SubjectDAO subjectDAO) {        super.setSubjectDAO(subjectDAO);    //设置sessionManager到DefaultSubjectDAO的SessionStorageEvaluator        applySessionManagerToSessionStorageEvaluatorIfPossible();    }    //在sessionManager被设置后,设置sessionManager到DefaultSubjectDAO的SessionStorageEvaluator    @Override    protected void afterSessionManagerSet() {        super.afterSessionManagerSet();        applySessionManagerToSessionStorageEvaluatorIfPossible();    }    //设置sessionManager到DefaultSubjectDAO的SessionStorageEvaluator    private void applySessionManagerToSessionStorageEvaluatorIfPossible() {        SubjectDAO subjectDAO = getSubjectDAO();        if (subjectDAO instanceof DefaultSubjectDAO) {            SessionStorageEvaluator evaluator = ((DefaultSubjectDAO)subjectDAO).getSessionStorageEvaluator();            if (evaluator instanceof DefaultWebSessionStorageEvaluator) {                ((DefaultWebSessionStorageEvaluator)evaluator).setSessionManager(getSessionManager());            }        }    }    @Override    protected SubjectContext copy(SubjectContext subjectContext) {        if (subjectContext instanceof WebSubjectContext) {            return new DefaultWebSubjectContext((WebSubjectContext) subjectContext);        }        return super.copy(subjectContext);    }    @SuppressWarnings({"UnusedDeclaration"})    @Deprecated    public String getSessionMode() {        return sessionMode;    }    /**     * @param sessionMode     * @deprecated since 1.2     */    @Deprecated    public void setSessionMode(String sessionMode) {        log.warn("The 'sessionMode' property has been deprecated.  Please configure an appropriate WebSessionManager " +                "instance instead of using this property.  This property/method will be removed in a later version.");        String mode = sessionMode;        if (mode == null) {            throw new IllegalArgumentException("sessionMode argument cannot be null.");        }        mode = sessionMode.toLowerCase();        if (!HTTP_SESSION_MODE.equals(mode) && !NATIVE_SESSION_MODE.equals(mode)) {            String msg = "Invalid sessionMode [" + sessionMode + "].  Allowed values are " +                    "public static final String constants in the " + getClass().getName() + " class: '"                    + HTTP_SESSION_MODE + "' or '" + NATIVE_SESSION_MODE + "', with '" +                    HTTP_SESSION_MODE + "' being the default.";            throw new IllegalArgumentException(msg);        }        boolean recreate = this.sessionMode == null || !this.sessionMode.equals(mode);        this.sessionMode = mode;        if (recreate) {            LifecycleUtils.destroy(getSessionManager());            SessionManager sessionManager = createSessionManager(mode);            this.setInternalSessionManager(sessionManager);        }    }    @Override    public void setSessionManager(SessionManager sessionManager) {        this.sessionMode = null;        if (sessionManager != null && !(sessionManager instanceof WebSessionManager)) {            if (log.isWarnEnabled()) {                String msg = "The " + getClass().getName() + " implementation expects SessionManager instances " +                        "that implement the " + WebSessionManager.class.getName() + " interface.  The " +                        "configured instance is of type [" + sessionManager.getClass().getName() + "] which does not " +                        "implement this interface..  This may cause unexpected behavior.";                log.warn(msg);            }        }        setInternalSessionManager(sessionManager);    }    /**     * @param sessionManager     * @since 1.2     */    private void setInternalSessionManager(SessionManager sessionManager) {        super.setSessionManager(sessionManager);    }    //判断是否是使用httpSession    public boolean isHttpSessionMode() {        SessionManager sessionManager = getSessionManager();        return sessionManager instanceof WebSessionManager && ((WebSessionManager)sessionManager).isServletContainerSessions();    }    protected SessionManager createSessionManager(String sessionMode) {        if (sessionMode == null || !sessionMode.equalsIgnoreCase(NATIVE_SESSION_MODE)) {            log.info("{} mode - enabling ServletContainerSessionManager (HTTP-only Sessions)", HTTP_SESSION_MODE);            return new ServletContainerSessionManager();        } else {            log.info("{} mode - enabling DefaultWebSessionManager (non-HTTP and HTTP Sessions)", NATIVE_SESSION_MODE);            return new DefaultWebSessionManager();        }    }    @Override    protected SessionContext createSessionContext(SubjectContext subjectContext) {        SessionContext sessionContext = super.createSessionContext(subjectContext);        if (subjectContext instanceof WebSubjectContext) {            WebSubjectContext wsc = (WebSubjectContext) subjectContext;            ServletRequest request = wsc.resolveServletRequest();            ServletResponse response = wsc.resolveServletResponse();            DefaultWebSessionContext webSessionContext = new DefaultWebSessionContext(sessionContext);            if (request != null) {                webSessionContext.setServletRequest(request);            }            if (response != null) {                webSessionContext.setServletResponse(response);            }            sessionContext = webSessionContext;        }        return sessionContext;    }    @Override    protected SessionKey getSessionKey(SubjectContext context) {        if (WebUtils.isWeb(context)) {            Serializable sessionId = context.getSessionId();            ServletRequest request = WebUtils.getRequest(context);            ServletResponse response = WebUtils.getResponse(context);            return new WebSessionKey(sessionId, request, response);        } else {            return super.getSessionKey(context);        }    }    @Override    protected void beforeLogout(Subject subject) {        super.beforeLogout(subject);        removeRequestIdentity(subject);    }    protected void removeRequestIdentity(Subject subject) {        if (subject instanceof WebSubject) {            WebSubject webSubject = (WebSubject) subject;            ServletRequest request = webSubject.getServletRequest();            if (request != null) {                request.setAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY, Boolean.TRUE);            }        }    }}
2 0