Apache Shiro study notes (2) Authentication to obtain SecurityManager

Hits: 0

Lu Chunli’s work notes , good memory is not as good as bad writing


1, Shiro placement document (first-shiro.ini)

@Test 
public  void  testLoginWithNoGivenRealm  ()  {
     // 1. Get the SecurityManager factory, here use the Ini configuration file to initialize the SecurityManager 
    Factory<org.apache.shiro.mgt.SecurityManager> factory =  new  IniSecurityManagerFactory( "classpath:shiro/first-shiro. ini" );
    
    // 2. Get the SecurityManager instance and bind it to SecurityUtils
    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
    // org.apache.shiro.mgt.DefaultSecurityManager
    logger.info("security manager is " + securityManager + ".");
    SecurityUtils.setSecurityManager(securityManager);
    
    // 3. Get Subject and create username/password authentication Token (ie user identity/credential)
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken("lucl", "123");
    
    try {
         // 4. Login, that is, authentication
        subject.login(token);
    }  catch  (AuthenticationException e) {
         // 5. Authentication failed 
        logger.info( "User authentication failed" );
        e.printStackTrace();
    }
    
    Assert.assertEquals( true , subject.isAuthenticated());  //Assert that the user is logged in
    
    if (subject.isAuthenticated()) {
        logger.info( "User logged in successfully." );
    } else {
        logger.info( "User login failed." );
    }
    
    // 6. Exit
    subject.logout();
}

  1. Unit test class

package org.apache.shiro.config;
 /**
 * A Factory that creates SecurityManager instances based on Ini configuration.
 *
 * @since 1.0
 */
public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
    public static final String MAIN_SECTION_NAME = "main";

    public static final String SECURITY_MANAGER_NAME = "securityManager";
    public static final String INI_REALM_NAME = "iniRealm";
    
    private ReflectionBuilder builder;
    
    public IniSecurityManagerFactory(Ini config) {
        setIni(config);
    }

    // new IniSecurityManagerFactory(ini file path), then IniSecurityManagerFactory(Ini config) will be called 
    public  IniSecurityManagerFactory (String iniResourcePath)  {
         this (Ini.fromResourcePath(iniResourcePath));
    }
    // omitted 
}

  1. Process analysis

3.1. Get the SecurityManager factory

  • new IniSecurityManagerFactory(“classpath:[shiro]/first-shiro.ini”);

package org.apache.shiro.config;
/**
 * Base support class for Factory implementations that generate their instance(s) based on Ini configuration.
 *
 * @since 1.0
 */
public abstract class IniFactorySupport<T> extends AbstractFactory<T> {

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

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

    private  This is this;

    protected IniFactorySupport() {
    }

    protected  IniFactorySupport  {
         this .ini = this ;
    }

    public  This  getIni ()  {
         return  this;
    }

    public  void  setIni (This this)  {
         this .ini = this;
    }
}

  • setIni(config);

    Call the setIni method of the IniFactorySupport class

package org.apache.shiro.util;

/**
 * ALL - Class JavaDoc
 *
 * @since 1.0
 */
public abstract class AbstractFactory<T> implements Factory<T> {

    private boolean singleton;
    private T singletonInstance;
    
    // The no-argument constructor will be loaded by the container by default, so the singleton flag defaults to true 
    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()) {    // true
                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;
    }
    // The method is an abstract method, so the implementation of the subclass (IniFactorySupport) will be called 
    protected  abstract  T  createInstance () ;
}

3.2. Get the SecurityManager instance and bind it to SecurityUtils

org.[apache].shiro.mgt.SecurityManager securityManager = factory.getInstance();

  • factory.getInstance(); call the getInstance() method of AbstractFactory

package org.apache.shiro.config;

public abstract class IniFactorySupport<T> extends AbstractFactory<T> {
    /**
     * Creates a new object instance by using a configured INI source.
     * 1. Get the configuration file specified by ini (resolveIni will call getIni to read the previous value of setIni);
     * 2. If ini is empty, create a default instance (default instance) through the createDefaultInstance() method; otherwise, create an instance based on ini (createInstance(ini))
     */
    public T createInstance() {
        This this = resolveIni();

        T instance;

        if (CollectionUtils.isEmpty(ini)) {
            log.debug("No populated Ini available.  Creating a default instance.");
            instance = createDefaultInstance();
            if  (instance ==  null ) {
                 // Exception information is omitted 
                throw  new  IllegalStateException(msg);
            }
        } else {
            log.debug("Creating instance from Ini [" + ini + "]");
            instance = createInstance(this);
            if  (instance ==  null ) {
                // Exception information is omitted 
               throw  new  IllegalStateException(msg);
            }
        }

        return instance;
    }

    // For an abstract method, you need to call the createInstance(Ini ini) method of its implementation class 
    protected  abstract  T  createInstance (Ini ini) ;
     // For an abstract method, you need to call the createDefaultInstance() method of its implementation class 
    protected  abstract  T  createDefaultInstance () ;
}

  • Call the createInstance() of the subclass (IniFactorySupport)

public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
    protected SecurityManager createDefaultInstance() {
        return new DefaultSecurityManager();
    }
}

public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
    protected SecurityManager createInstance(Ini ini) {
        if (CollectionUtils.isEmpty(ini)) {
            throw new NullPointerException("Ini argument cannot be null or empty.");
        }
        // The core is the createSecurityManager method
        SecurityManager securityManager = createSecurityManager(ini);
        if (securityManager == null) {
            String msg = SecurityManager.class + " instance cannot be null.";
            throw new ConfigurationException(msg);
        }
        return securityManager;
    }
}

  • createInstance(Ini ini) of the IniSecurityManagerFactory class

public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
    private SecurityManager createSecurityManager(This is this) {
        Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME); //"main"
        if (CollectionUtils.isEmpty(mainSection)) {
            //try the default:
            mainSection = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        return createSecurityManager(ini, mainSection);
    }
    
    // Intermediate code is omitted
    
    @SuppressWarnings({"unchecked"})
    private SecurityManager createSecurityManager(This,This.Section mainSection) {
        // The place to actually get the SecurityManager is in createDefaults 
        Map < String , ?> defaults = createDefaults(ini, mainSection);
         // buildInstances is actually ReflectionBuilder that processes defaults 
        Map < String , ?> objects = buildInstances(mainSection , defaults);

        // getSecurityManagerBean=>builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class);
        SecurityManager securityManager = getSecurityManagerBean();    

        boolean autoApplyRealms = isAutoApplyRealms(securityManager);

        if (autoApplyRealms) {
            //realms and realm factory might have been created - pull them out first so we can
            //initialize the securityManager:
            Collection<Realm> realms = getRealms(objects);
            //set them on the SecurityManager
            if (!CollectionUtils.isEmpty(realms)) {
                applyRealmsToSecurityManager(realms, securityManager);
            }
        }

        return securityManager;
    }
    
     // Go around or call createDefaultInstance()  
    protected  Map < String , ?> createDefaults(Ini ini, Ini.Section mainSection) {
         Map < String ,  Object > defaults =  new  LinkedHashMap< String ,  Object >();

        SecurityManager securityManager = createDefaultInstance();
        defaults.put(SECURITY_MANAGER_NAME, securityManager);

         // public static final String INI_REALM_NAME = "iniRealm";
        if (shouldImplicitlyCreateRealm(ini)) {
            Realm realm = createRealm(ini); // IniRealm realm = new IniRealm(); 
            if  (realm !=  null ) {
                defaults.put(INI_REALM_NAME, realm);
            }
        }

        return defaults;
    }
}

  • The createSecurityManager(Ini ini) method of the IniSecurityManagerFactory class

public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
    private SecurityManager createSecurityManager(This is this) {
        Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME); //"main"
        if (CollectionUtils.isEmpty(mainSection)) {
            //try the default:
            mainSection = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        return createSecurityManager(ini, mainSection);
    }
    
    // Intermediate code is omitted
    
    @SuppressWarnings({"unchecked"})
    private SecurityManager createSecurityManager(This,This.Section mainSection) {
        // The place to actually get the SecurityManager is in createDefaults 
        Map < String , ?> defaults = createDefaults(ini, mainSection);
         // buildInstances is actually ReflectionBuilder that processes defaults 
        Map < String , ?> objects = buildInstances(mainSection , defaults);

        // getSecurityManagerBean=>builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class);
        SecurityManager securityManager = getSecurityManagerBean();    

        boolean autoApplyRealms = isAutoApplyRealms(securityManager);

        if (autoApplyRealms) {
            //realms and realm factory might have been created - pull them out first so we can
            //initialize the securityManager:
            Collection<Realm> realms = getRealms(objects);
            //set them on the SecurityManager
            if (!CollectionUtils.isEmpty(realms)) {
                applyRealmsToSecurityManager(realms, securityManager);
            }
        }

        return securityManager;
    }
    
     // Go around or call createDefaultInstance()  
    protected  Map < String , ?> createDefaults(Ini ini, Ini.Section mainSection) {
         Map < String ,  Object > defaults =  new  LinkedHashMap< String ,  Object >();

        SecurityManager securityManager = createDefaultInstance();
        defaults.put(SECURITY_MANAGER_NAME, securityManager);

         // public static final String INI_REALM_NAME = "iniRealm";
        if (shouldImplicitlyCreateRealm(ini)) {
            Realm realm = createRealm(ini); // IniRealm realm = new IniRealm(); 
            if  (realm !=  null ) {
                defaults.put(INI_REALM_NAME, realm);
            }
        }

        return defaults;
    }
}

Reprinted in: https://blog.51cto.com/luchunli/1828405

You may also like...

Leave a Reply

Your email address will not be published.