Shiro身份认证流程,securityManager源码解析

发布时间:2024-01-10 18:35:36

http://shiro.apache.org/tutorial.html 跟着教程学习如何验证你的身份,先是简单的身份验证

shiro.ini

[users]
zhang=123
wang=123

重点内容

 @Test
    public void testHelloworld() {
        //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
        Factory<org.apache.shiro.mgt.SecurityManager> factory =
                new IniSecurityManagerFactory("classpath:shiro.ini");

        //2、得到SecurityManager实例 并绑定给SecurityUtils
        org.apache.shiro.mgt.SecurityManager securityManager 
          = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);


        //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");

        try {
            //4、登录,即身份验证
            subject.login(token);
        } catch (AuthenticationException e) {
            //5、身份验证失败
        }

        Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
        //6、退出
        subject.logout();
    }

1 跟着源码看看加载工厂,看看加载工厂的流程,有很多的设计思想,好久没看设计模式了,反正就是面向接口编程
factory

public interface Factory<T> {

    T getInstance();
}

看到没有,这里用到了模板模式,其实也不太算吧,模板是按照某种运行的模式进行运行,给继承的子类,扩展的机会,这样可以按照我们的思路进行处理。
protected abstract T createInstance();

public abstract class AbstractFactory<T> implements Factory<T> {

    private boolean singleton;
    private T singletonInstance;

    public AbstractFactory() {
        this.singleton = true;
    }

    public boolean isSingleton() {
        return singleton;
    }

    public void setSingleton(boolean singleton) {
        this.singleton = singleton;
    }

    public T getInstance() {
        T instance;
        if (isSingleton()) {
            if (this.singletonInstance == null) {
                this.singletonInstance = createInstance();
            }
            instance = this.singletonInstance;
        } else {
            instance = createInstance();
        }
        if (instance == null) {
            String msg = "Factory 'createInstance' implementation returned a null object.";
            throw new IllegalStateException(msg);
        }
        return instance;
    }

    protected abstract T createInstance();
}

这里通过之前读取配置文件信息获取到的Ini类的信息(从配置文件中获取的信息),用来初始化securityManager,如果没有初始化默认的配置信息,这里在一次给子类来创建信息,和之前的写法类似


public abstract class IniFactorySupport<T> extends AbstractFactory<T> {

    public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";

    private Ini ini;

    protected IniFactorySupport() {
    }

    protected IniFactorySupport(Ini ini) {
        this.ini = ini;
    }
    public Ini getIni() {
        return ini;
    }
    public void setIni(Ini ini) {
        this.ini = ini;
    }
    public static Ini loadDefaultClassPathIni() {
        Ini ini = null;
        if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
            ini = new Ini();
            ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
            if (CollectionUtils.isEmpty(ini)) {

            }
        }
        return ini;
    }
    protected Ini resolveIni() {
        Ini ini = getIni();
        if (CollectionUtils.isEmpty(ini)) {
            ini = loadDefaultClassPathIni();
        }
        return ini;
    }

    public T createInstance() {
        Ini ini = resolveIni();
        T instance;
        if (CollectionUtils.isEmpty(ini)) {
            log.debug("No populated Ini available.  Creating a default instance.");
            instance = createDefaultInstance();
            if (instance == null) {
                String msg = getClass().getName();
                throw new IllegalStateException(msg);
            }
        } else {
            log.debug("Creating instance from Ini [" + ini + "]");
            instance = createInstance(ini);
            if (instance == null) {
                String msg = getClass().getName();
                throw new IllegalStateException(msg);
            }
        }

        return instance;
    }

    protected abstract T createInstance(Ini ini);

    protected abstract T createDefaultInstance();
}

Ini 就是把配置文件信息读取出来的一个处理类。
这里写图片描述

IniSecurityManagerFactory 工程继续继承 IniFactorySupport继续处理,这个就是我们初始化的最后个工厂类的信息

 //举个简单的吧,Ini创建的太复杂了,需要初始化很多的信息,这里就是创建默认的工厂
  protected SecurityManager createDefaultInstance() {
        return new DefaultSecurityManager();
    }
 //然后看看这个默认的DefaultSecurityManager管家,看看继承图片,发现为什么管家有很多的功能!它管理着所有Subject、且负责进行认证和授权、及会话、缓存的管理。全部都被继承进来了,通过SecurityManager接口就可以创建无缝的对接啊,太强大了。下面的成员中看看成员就知道了,啥子意思了。
    protected RememberMeManager rememberMeManager;
    protected SubjectDAO subjectDAO;
    protected SubjectFactory subjectFactory;
    /**
     * Default no-arg constructor.
     */
    public DefaultSecurityManager() {
        super();
        this.subjectFactory = new DefaultSubjectFactory();
        this.subjectDAO = new DefaultSubjectDAO();
    }

这里写图片描述

这里的管家都是基本上利用代理模式处理,而且代理的全部都是接口,还有就是留了很多的函数,当调用父类设置的时候,同时调用子类的处理函数,很高端的用法–模板方法,在设计模式中有的


public abstract class CachingSecurityManager
      implements SecurityManager, Destroyable,
      CacheManagerAware {

    /**
     * The CacheManager to use to perform caching operations to enhance performance.  Can be null.
     */
    // 这里就是代理模式,创建一个成员变量,在里面使用当前接口的实现类的信息
    //都是使用接口处理,太牛了 
    private CacheManager cacheManager;


    public CachingSecurityManager() {
    }


    public CacheManager getCacheManager() {
        return cacheManager;
    }

    /**
     * Sets the CacheManager used by this {@code SecurityManager} and potentially any of its
     * children components.
     * <p/>
     * After the cacheManager attribute has been set, the template method
     * {@link #afterCacheManagerSet afterCacheManagerSet()} is 
      executed to allow subclasses to adjust when a
     * cacheManager is available.
     * 看到没有这里就是模板方法啊,调用子类的信息哦!哈哈,一种非常高级的技能
     * @param cacheManager the CacheManager used by this
         {@code SecurityManager} and potentially any of its
     *                     children components.
     */
    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
        afterCacheManagerSet();
    }

    /**
     * Template callback to notify subclasses that a
     * {@link org.apache.shiro.cache.CacheManager CacheManager}
      has been set and is available for use via the
     * {@link #getCacheManager getCacheManager()} method.
     */
    protected void afterCacheManagerSet() {
    }

    /**
     * Destroys the {@link #getCacheManager() cacheManager}
     via {@link LifecycleUtils#destroy LifecycleUtils.destroy}.
     */
    public void destroy() {
        LifecycleUtils.destroy(getCacheManager());
        this.cacheManager = null;
    }

}

Realm 管理也是一样的,使用了代理模板~,注入成员函数去处理

public abstract class RealmSecurityManager extends CachingSecurityManager {

   // 各种各样的,可以通过Ini配置进行处理哦~,然后获取就可以进行处理了
    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();
    }

    public Collection<Realm> getRealms() {
        return realms;
    }

}

Authenticator 认证信息,代理


public abstract class AuthenticatingSecurityManager extends RealmSecurityManager {

    /**
     * The internal <code>Authenticator</code>
     delegate instance that this SecurityManager instance will use
     * to perform all authentication operations.
     代理所有的 Authenticator(证明者,认证者;密码证明信号)
     */
    private Authenticator authenticator;

    /**
     * Default no-arg constructor that initializes its internal
     * <code>authenticator</code> instance to a
     * {@link org.apache.shiro.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator}.
     */
    public AuthenticatingSecurityManager() {
        super();
        this.authenticator = new ModularRealmAuthenticator();
    }

    public Authenticator getAuthenticator() {
        return authenticator;
    }

   //设置自定义的验证器,很好的扩展
    public void setAuthenticator(Authenticator authenticator)
        throws IllegalArgumentException {
        if (authenticator == null) {
            String msg = "Authenticator argument cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        this.authenticator = authenticator;
    }

    /**
     * Passes on the {@link #getRealms() realms} to 
       the internal delegate <code>Authenticator</code> instance so
     * that it may use them during authentication attempts.
     */
    protected void afterRealmsSet() {
        super.afterRealmsSet();
        if (this.authenticator instanceof ModularRealmAuthenticator) {
            ((ModularRealmAuthenticator) this.authenticator).setRealms(getRealms());
        }
    }

    /**
     * 代理啊!!哈哈
     */
    public AuthenticationInfo authenticate(AuthenticationToken token)
    throws AuthenticationException {
        return this.authenticator.authenticate(token);
    }


}

Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能


public abstract class AuthenticatingSecurityManager extends RealmSecurityManager {

    /**
     * The internal <code>Authenticator</code>
      delegate instance that this SecurityManager instance will use
     * to perform all authentication operations.
     代理信息
     */
    private Authenticator authenticator;

    public AuthenticatingSecurityManager() {
        super();
        this.authenticator = new ModularRealmAuthenticator();
    }
    public Authenticator getAuthenticator() {
        return authenticator;
    }

    /**
    设置自定义访问控制器
    **/
    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());
        }
    }


    public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
        return this.authenticator.authenticate(token);
    }

}

session管理,这些代码写的非常的经典啊,格式非常的相同


public abstract class SessionsSecurityManager extends AuthorizingSecurityManager {

    /**
     * The internal delegate <code>SessionManager</code> used by this security manager that manages all the
     * application's {@link Session Session}s.
     */
    private SessionManager sessionManager;

    /**
     * Default no-arg constructor, internally creates a suitable default 
     {@link SessionManager SessionManager} delegate
     * instance.
     */
    public SessionsSecurityManager() {
        super();
        this.sessionManager = new DefaultSessionManager();
        applyCacheManagerToSessionManager();
    }


    public void setSessionManager(SessionManager sessionManager) {
        this.sessionManager = sessionManager;
        afterSessionManagerSet();
    }

    protected void afterSessionManagerSet() {
        applyCacheManagerToSessionManager();
    }

    public SessionManager getSessionManager() {
        return this.sessionManager;
    }

    protected void afterCacheManagerSet() {
        super.afterCacheManagerSet();
        applyCacheManagerToSessionManager();
    }

    protected void applyCacheManagerToSessionManager() {
        if (this.sessionManager instanceof CacheManagerAware) {
            ((CacheManagerAware) this.sessionManager).setCacheManager(getCacheManager());
        }
    }
    public Session start(SessionContext context) throws AuthorizationException {
        return this.sessionManager.start(context);
    }
    public Session getSession(SessionKey key) throws SessionException {
        return this.sessionManager.getSession(key);
    }
    public void destroy() {
        LifecycleUtils.destroy(getSessionManager());
        this.sessionManager = null;
        super.destroy();
    }
}

身份验证还是没有讲…..这个超标了,主要是觉得代码写的非常的好!

文章来源:https://wangji.blog.csdn.net/article/details/53699505
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。