欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

ApacheShiro源碼解讀之SecurityManager的創(chuàng)建

對(duì)于Shiro(v1.2+)的SecurityManager的創(chuàng)建,在普通的應(yīng)用程序中一般可以在main方法中這么創(chuàng)建

成都創(chuàng)新互聯(lián)主營(yíng)洪洞網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,重慶App定制開(kāi)發(fā),洪洞h5微信小程序開(kāi)發(fā)搭建,洪洞網(wǎng)站營(yíng)銷推廣歡迎洪洞等地區(qū)企業(yè)咨詢

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();

該方法讀取classpath路徑下的shiro.ini文件來(lái)構(gòu)建SecurityManager,然而在web應(yīng)用程序中,其是怎么創(chuàng)建的我們接下來(lái)逐步分析。

在web環(huán)境中我們會(huì)使用以下的Listener,而SecurityManager的創(chuàng)建就在Listener的初始化過(guò)程中【該Listener在shrio-web.jar中】

<listener>
        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>

EnvironmentLoaderListener的繼承關(guān)系很簡(jiǎn)單,如下所示
Apache Shiro源碼解讀之SecurityManager的創(chuàng)建

EnvironmentLoader的作用是負(fù)責(zé)在應(yīng)用程序啟動(dòng)的時(shí)候負(fù)責(zé)加載Shiro,同時(shí)將org.apache.shiro.web.mgt.WebSecurityManager設(shè)置到ServletContext中。

在初始化Shiro的過(guò)程中,在web.xml文件中配置的上下文參數(shù)“shiroEnvironmentClass”和“shiroConfigLocations”可以指導(dǎo)Shiro的初始化過(guò)程,當(dāng)然,這兩個(gè)參數(shù)不是必須配置的,有默認(rèn)值。

shiroEnvironmentClass:制定繼承自WebEnvironment的自定義類,默認(rèn)對(duì)象為IniWebEnvironment。
shiroConfigLocations:制定shiro初始化時(shí)用的配置文件路徑,默認(rèn)會(huì)先查詢/WEB-INF/shiro.ini,如果沒(méi)找到再查找classpath:shiro.ini。

public class EnvironmentLoaderListener extends EnvironmentLoader implements ServletContextListener {

    /**
     * Initializes the Shiro {@code WebEnvironment} and binds it to the {@code ServletContext} at application
     * startup for future reference.
     *
     * @param sce the ServletContextEvent triggered upon application startup
     */
    public void contextInitialized(ServletContextEvent sce) {
        initEnvironment(sce.getServletContext());
    }

    /**
     * Destroys any previously created/bound {@code WebEnvironment} instance created by
     * the {@link #contextInitialized(javax.servlet.ServletContextEvent)} method.
     *
     * @param sce the ServletContextEvent triggered upon application shutdown
     */
    public void contextDestroyed(ServletContextEvent sce) {
        destroyEnvironment(sce.getServletContext());
    }
}
public class EnvironmentLoader {
    public WebEnvironment initEnvironment(ServletContext servletContext) throws IllegalStateException {

        if (servletContext.getAttribute(ENVIRONMENT_ATTRIBUTE_KEY) != null) {
            String msg = "There is already a Shiro environment associated with the current ServletContext.  " +
                    "Check if you have multiple EnvironmentLoader* definitions in your web.xml!";
            throw new IllegalStateException(msg);
        }

        servletContext.log("Initializing Shiro environment");
        log.info("Starting Shiro environment initialization.");

        long startTime = System.currentTimeMillis();

        try {

            WebEnvironment environment = createEnvironment(servletContext);
            servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY,environment);

            log.debug("Published WebEnvironment as ServletContext attribute with name [{}]",
                    ENVIRONMENT_ATTRIBUTE_KEY);

            if (log.isInfoEnabled()) {
                long elapsed = System.currentTimeMillis() - startTime;
                log.info("Shiro environment initialized in {} ms.", elapsed);
            }

            return environment;
        } catch (RuntimeException ex) {
            log.error("Shiro environment initialization failed", ex);
            servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, ex);
            throw ex;
        } catch (Error err) {
            log.error("Shiro environment initialization failed", err);
            servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, err);
            throw err;
        }
    }

    protected WebEnvironment createEnvironment(ServletContext sc) {

        //查找WebEnvironment對(duì)象,并將其實(shí)例化
        WebEnvironment webEnvironment = determineWebEnvironment(sc);
        if (!MutableWebEnvironment.class.isInstance(webEnvironment)) {
            throw new ConfigurationException("Custom WebEnvironment class [" + webEnvironment.getClass().getName() +
                    "] is not of required type [" + MutableWebEnvironment.class.getName() + "]");
        }

        String configLocations = sc.getInitParameter(CONFIG_LOCATIONS_PARAM);
        boolean configSpecified = StringUtils.hasText(configLocations);

        if (configSpecified && !(ResourceConfigurable.class.isInstance(webEnvironment))) {
            String msg = "WebEnvironment class [" + webEnvironment.getClass().getName() + "] does not implement the " +
                    ResourceConfigurable.class.getName() + "interface.  This is required to accept any " +
                    "configured " + CONFIG_LOCATIONS_PARAM + "value(s).";
            throw new ConfigurationException(msg);
        }

        MutableWebEnvironment environment = (MutableWebEnvironment) webEnvironment;
        //保存當(dāng)前的ServletContext對(duì)象
        environment.setServletContext(sc);

        //如果在web.xml設(shè)置了配置文件的路徑,則在此設(shè)置到environment中
        if (configSpecified && (environment instanceof ResourceConfigurable)) {
            ((ResourceConfigurable) environment).setConfigLocations(configLocations);
        }

        //構(gòu)造方法,默認(rèn)未實(shí)現(xiàn)
        customizeEnvironment(environment);

        //調(diào)用environment的init方法初始化environment對(duì)象
        LifecycleUtils.init(environment);

        return environment;
    }

    protected WebEnvironment determineWebEnvironment(ServletContext servletContext) {

        //從ServletContext的參數(shù)中獲取WebEnvironment的配置--shiroEnvironmentClass,如果有則創(chuàng)建實(shí)例返回
        Class<? extends WebEnvironment> webEnvironmentClass = webEnvironmentClassFromServletContext(servletContext);
        WebEnvironment webEnvironment = null;

        // 嘗試通過(guò)Java的ServiceLoader來(lái)查找WebEnvironment的實(shí)現(xiàn)類
        if (webEnvironmentClass == null) {
            webEnvironment = webEnvironmentFromServiceLoader();
        }

        // 如果上面的步驟都沒(méi)找到,則使用默認(rèn)的WebEnvironment實(shí)現(xiàn)類IniWebEnvironment
        if (webEnvironmentClass == null && webEnvironment == null) {
            webEnvironmentClass = getDefaultWebEnvironmentClass();
        }

        // 創(chuàng)建WebEnvironment的實(shí)例
        if (webEnvironmentClass != null) {
            webEnvironment = (WebEnvironment) ClassUtils.newInstance(webEnvironmentClass);
        }

        return webEnvironment;
    }

    private WebEnvironment webEnvironmentFromServiceLoader() {

        WebEnvironment webEnvironment = null;
        /*
         * 使用Java的ServiceLoader方式來(lái)查找WebEnvironment的實(shí)現(xiàn)類(查找jar包中META-INF下的services文件夾中的文件);
         * 例如在某個(gè)services文件夾中有個(gè)名為org.apache.shiro.web.env.WebEnvironment的文件,然后在文件里面保存WebEnvironment的實(shí)現(xiàn)類全路徑;
         * 可見(jiàn),文件名為接口的全路徑,里面的內(nèi)容為接口的實(shí)現(xiàn)類
         * */
        ServiceLoader<WebEnvironment> serviceLoader = ServiceLoader.load(WebEnvironment.class);
        Iterator<WebEnvironment> iterator = serviceLoader.iterator();

        // 如果找到則使用第一個(gè)
        if (iterator.hasNext()) {
            webEnvironment = iterator.next();
        }
        // 如果不止找到一個(gè),則拋出異常
        if (iterator.hasNext()) {
            List<String> allWebEnvironments = new ArrayList<String>();
            allWebEnvironments.add(webEnvironment.getClass().getName());
            while (iterator.hasNext()) {
                allWebEnvironments.add(iterator.next().getClass().getName());
            }
            throw new ConfigurationException("ServiceLoader for class [" + WebEnvironment.class + "] returned more then one " +
                    "result.  ServiceLoader must return zero or exactly one result for this class. Select one using the " +
                    "servlet init parameter '"+ ENVIRONMENT_CLASS_PARAM +"'. Found: " + allWebEnvironments);
        }
        return webEnvironment;
    }
}

綜上得知,查找WebEnvironment的實(shí)現(xiàn)類經(jīng)歷了三次查找
1)從ServletContext的初始化參數(shù)
2)從jar包查找實(shí)現(xiàn)類
3)使用默認(rèn)的IniWebEnvironment

在得到WebEnvironment的實(shí)現(xiàn)類并創(chuàng)建好實(shí)例后,接著便會(huì)調(diào)用其init方法,這里假設(shè)得到的是默認(rèn)的IniWebEnvironment。

public class IniWebEnvironment extends ResourceBasedWebEnvironment implements Initializable, Destroyable {

    public static final String DEFAULT_WEB_INI_RESOURCE_PATH = "/WEB-INF/shiro.ini";
    public static final String FILTER_CHAIN_RESOLVER_NAME = "filterChainResolver";

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

    /**
     * The Ini that configures this WebEnvironment instance.
     */
    private Ini ini;

    private WebIniSecurityManagerFactory factory;

    public IniWebEnvironment() {
        //實(shí)例化WebIniSecurityManagerFactory對(duì)象
        factory = new WebIniSecurityManagerFactory();
    }

    /**
     * 初始化本實(shí)例
     */
    public void init() {
        //解析shiiro.ini配置文件并生成對(duì)應(yīng)的Ini實(shí)例
        setIni(parseConfig());

        //使用Ini信息,通過(guò)WebIniSecurityManagerFactory創(chuàng)建WebSecurityManager實(shí)例
        configure();
    }
}

protected Ini parseConfig() {
        //直接取,首次運(yùn)行肯定為null
        Ini ini = getIni();

        //獲取配置文件路徑【該路徑信息就是web.xml文件中配置的,實(shí)例化該類的時(shí)候已經(jīng)在EnvironmentLoader中設(shè)置】
        String[] configLocations = getConfigLocations();

        if (log.isWarnEnabled() && !CollectionUtils.isEmpty(ini) &&
                configLocations != null && configLocations.length > 0) {
            //如果Ini對(duì)象不為空,并且configLocations也不為空,給出提示信息
            log.warn("Explicit INI instance has been provided, but configuration locations have also been " +
                    "specified.  The {} implementation does not currently support multiple Ini config, but this may " +
                    "be supported in the future. Only the INI instance will be used for configuration.",
                    IniWebEnvironment.class.getName());
        }

        if (CollectionUtils.isEmpty(ini)) {
            log.debug("Checking any specified config locations.");
            //從指定路徑下的配置文件中創(chuàng)建Ini實(shí)例
            ini = getSpecifiedIni(configLocations);
        }

        if (CollectionUtils.isEmpty(ini)) {
            log.debug("No INI instance or config locations specified.  Trying default config locations.");
            /*
             * 如果沒(méi)有在web.xml中配置,則從默認(rèn)的路徑下讀取配置文件并創(chuàng)建實(shí)例
             * 1,/WEB-INF/shiro.ini
             * 2,classpath:shiro.ini
             * */
            ini = getDefaultIni();
        }

        /*
         * 為了保持向后兼容而提供getFrameworkIni方法來(lái)創(chuàng)建Ini對(duì)象并與上面得到的Ini對(duì)象合并.
         * getFrameworkIni的默認(rèn)實(shí)現(xiàn)返回null,經(jīng)過(guò)合并處理后返回的還是上面的Ini對(duì)象
         * */
        ini = mergeIni(getFrameworkIni(), ini);

        if (CollectionUtils.isEmpty(ini)) {
            String msg = "Shiro INI configuration was either not found or discovered to be empty/unconfigured.";
            throw new ConfigurationException(msg);
        }
        return ini;
    }

        /**
     * 解析配置文件創(chuàng)建Ini實(shí)例對(duì)象
     * */
    protected Ini createIni(String configLocation, boolean required) throws ConfigurationException {

        Ini ini = null;

        if (configLocation != null) {
            ini = convertPathToIni(configLocation, required);
        }
        if (required && CollectionUtils.isEmpty(ini)) {
            String msg = "Required configuration location '" + configLocation + "' does not exist or did not " +
                    "contain any INI configuration.";
            throw new ConfigurationException(msg);
        }

        return ini;
    }

        /**
     * 加載制定路徑的配置文件,然后將文件流作為參數(shù)調(diào)用Ini實(shí)例對(duì)象的load方法來(lái)初始化Ini對(duì)象
     * */
    private Ini convertPathToIni(String path, boolean required) {

        Ini ini = null;

        if (StringUtils.hasText(path)) {
            InputStream is = null;

            //SHIRO-178: Check for servlet context resource and not only resource paths:
            if (!ResourceUtils.hasResourcePrefix(path)) {
                is = getServletContextResourceStream(path);
            } else {
                try {
                    is = ResourceUtils.getInputStreamForPath(path);
                } catch (IOException e) {
                    if (required) {
                        throw new ConfigurationException(e);
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("Unable to load optional path '" + path + "'.", e);
                        }
                    }
                }
            }
            if (is != null) {
                ini = new Ini();
                ini.load(is);
            } else {
                if (required) {
                    throw new ConfigurationException("Unable to load resource path '" + path + "'");
                }
            }
        }

        return ini;
    }

再看看Ini對(duì)象的初始化過(guò)程

public class Ini implements Map<String, Ini.Section> {
    private static transient final Logger log = LoggerFactory.getLogger(Ini.class);

    public static final String DEFAULT_SECTION_NAME = ""; //empty string means the first unnamed section
    public static final String DEFAULT_CHARSET_NAME = "UTF-8";

    public static final String COMMENT_POUND = "#";
    public static final String COMMENT_SEMICOLON = ";";
    public static final String SECTION_PREFIX = "[";
    public static final String SECTION_SUFFIX = "]";

    protected static final char ESCAPE_TOKEN = '\\';

    private final Map<String, Section> sections;

    /**
     * Creates a new empty {@code Ini} instance.
     */
    public Ini() {
        this.sections = new LinkedHashMap<String, Section>();
    }

    public void load(InputStream is) throws ConfigurationException {
        if (is == null) {
            throw new NullPointerException("InputStream argument cannot be null.");
        }
        InputStreamReader isr;
        try {
            isr = new InputStreamReader(is, DEFAULT_CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            throw new ConfigurationException(e);
        }
        load(isr);
    }

    public void load(Reader reader) {
        Scanner scanner = new Scanner(reader);
        try {
            load(scanner);
        } finally {
            try {
                scanner.close();
            } catch (Exception e) {
                log.debug("Unable to cleanly close the InputStream scanner.  Non-critical - ignoring.", e);
            }
        }
    }

        public void load(Scanner scanner) {

        String sectionName = DEFAULT_SECTION_NAME;
        StringBuilder sectionContent = new StringBuilder();

        //循環(huán)讀取每一行
        while (scanner.hasNextLine()) {

            String rawLine = scanner.nextLine();
            //取出兩邊的空格
            String line = StringUtils.clean(rawLine);

            if (line == null || line.startsWith(COMMENT_POUND) || line.startsWith(COMMENT_SEMICOLON)) {
                //忽略空行和注釋
                continue;
            }
            //獲取section名稱,格式為 [main] 這種,此時(shí)返回“main”
            String newSectionName = getSectionName(line);
            if (newSectionName != null) {
                //前面section的配置信息收集完成,添加section配置
                addSection(sectionName, sectionContent);

                //為本次的section重置StringBuilder對(duì)象,用戶存放該section的配置信息
                sectionContent = new StringBuilder();

                sectionName = newSectionName;

                if (log.isDebugEnabled()) {
                    log.debug("Parsing " + SECTION_PREFIX + sectionName + SECTION_SUFFIX);
                }
            } else {
                //添加配置信息
                sectionContent.append(rawLine).append("\n");
            }
        }

        //添加Section的配置信息
        addSection(sectionName, sectionContent);
    }

    private void addSection(String name, StringBuilder content) {
        if (content.length() > 0) {
            String contentString = content.toString();
            String cleaned = StringUtils.clean(contentString);
            if (cleaned != null) {
                //構(gòu)建Section對(duì)象【靜態(tài)內(nèi)部類】
                Section section = new Section(name, contentString);
                if (!section.isEmpty()) {
                    //以鍵值對(duì)的方式保存Section對(duì)象
                    sections.put(name, section);
                }
            }
        }
    }

    public static class Section implements Map<String, String> {
            private final String name;
            private final Map<String, String> props;

            /*
         * 解析收集的配置信息,將配置信息保存到props對(duì)象中
         * */
        private Section(String name, String sectionContent) {
            if (name == null) {
                throw new NullPointerException("name");
            }
            this.name = name;
            Map<String,String> props;
            if (StringUtils.hasText(sectionContent) ) {
                props = toMapProps(sectionContent);
            } else {
                props = new LinkedHashMap<String,String>();
            }
            if ( props != null ) {
                this.props = props;
            } else {
                this.props = new LinkedHashMap<String,String>();
            }
        }

    }
}

到此,在IniWebEnvironment實(shí)例中通過(guò)解析配置文件得到了Ini對(duì)象,該對(duì)象里面保存了配置文件中的每個(gè)Section信息,那么接著就要使用該Ini對(duì)象來(lái)構(gòu)建WebSecurityManager了,也就是調(diào)用IniWebEnvironment 的configure方法

public class IniWebEnvironment extends ResourceBasedWebEnvironment implements Initializable, Destroyable {
    protected void configure() {
        //Map<String, Object>對(duì)象
        this.objects.clear();

        WebSecurityManager securityManager = createWebSecurityManager();
        setWebSecurityManager(securityManager);

        FilterChainResolver resolver = createFilterChainResolver();
        if (resolver != null) {
            setFilterChainResolver(resolver);
        }
    }

    protected Map<String, Object> getDefaults() {
        Map<String, Object> defaults = new HashMap<String, Object>();
        defaults.put(FILTER_CHAIN_RESOLVER_NAME, new IniFilterChainResolverFactory());
        return defaults;
    }

    protected WebSecurityManager createWebSecurityManager() {
        //已經(jīng)創(chuàng)建好的Ini對(duì)象
        Ini ini = getIni();
        if (!CollectionUtils.isEmpty(ini)) {
            factory.setIni(ini);
        }

        Map<String, Object> defaults = getDefaults();
        if (!CollectionUtils.isEmpty(defaults)) {
            factory.setDefaults(defaults);
        }
        //從WebIniSecurityManagerFactory實(shí)例中創(chuàng)建WebSecurityManager
        WebSecurityManager wsm = (WebSecurityManager)factory.getInstance();

        //SHIRO-306 - get beans after they've been created (the call was before the factory.getInstance() call,
        //which always returned null.
        Map<String, ?> beans = factory.getBeans();
        if (!CollectionUtils.isEmpty(beans)) {
            this.objects.putAll(beans);
        }

        return wsm;
    }
}

接著看看WebIniSecurityManagerFactory的getInstance方法的實(shí)現(xiàn)

Apache Shiro源碼解讀之SecurityManager的創(chuàng)建

由圖可見(jiàn),在調(diào)用getInstance方法的時(shí)候,其實(shí)執(zhí)行的是位于AbstractFactory中的getInstance方法

public abstract class AbstractFactory<T> implements Factory<T> {
    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;
    }
     /*
     * 子類(IniFactorySupport)實(shí)現(xiàn)創(chuàng)建實(shí)例的過(guò)程
     * */
    protected abstract T createInstance();
}
public abstract class IniFactorySupport<T> extends AbstractFactory<T> {
    public T createInstance() {
        /*
         * 獲取Ini對(duì)象,前面已經(jīng)設(shè)置進(jìn)來(lái)。
         * 如果ini對(duì)象不存在,還會(huì)從默認(rèn)的路徑來(lái)創(chuàng)建Ini對(duì)象
         * */
        Ini ini = resolveIni();

        T instance;

        if (CollectionUtils.isEmpty(ini)) { 
            //如果Ini對(duì)象不存在,則調(diào)動(dòng)子類(IniSecurityManagerFactory)使用默認(rèn)的SecurityManager實(shí)例對(duì)象
            log.debug("No populated Ini available.  Creating a default instance.");
            instance = createDefaultInstance();
            if (instance == null) {
                String msg = getClass().getName() + " implementation did not return a default instance in " +
                        "the event of a null/empty Ini configuration.  This is required to support the " +
                        "Factory interface.  Please check your implementation.";
                throw new IllegalStateException(msg);
            }
        } else {
            log.debug("Creating instance from Ini [" + ini + "]");
            //調(diào)用子類(IniSecurityManagerFactory),根據(jù)Ini對(duì)象的信息來(lái)構(gòu)建SecurityManager對(duì)象
            instance = createInstance(ini);
            if (instance == null) {
                String msg = getClass().getName() + " implementation did not return a constructed instance from " +
                        "the createInstance(Ini) method implementation.";
                throw new IllegalStateException(msg);
            }
        }

        return instance;
    }

    protected abstract T createInstance(Ini ini);

    protected abstract T createDefaultInstance();
}
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() {
        this.builder = new ReflectionBuilder();
    }

    //默認(rèn)的SecurityManager對(duì)象【其實(shí)被WebIniSecurityManagerFactory復(fù)寫(xiě),返回的是DefaultWebSecurityManager】
    protected SecurityManager createDefaultInstance() {
        return new DefaultSecurityManager();
    }

    //根據(jù)Ini來(lái)創(chuàng)建SecurityManager對(duì)象
    protected SecurityManager createInstance(Ini ini) {
        if (CollectionUtils.isEmpty(ini)) {
            throw new NullPointerException("Ini argument cannot be null or empty.");
        }
        SecurityManager securityManager = createSecurityManager(ini);
        if (securityManager == null) {
            String msg = SecurityManager.class + " instance cannot be null.";
            throw new ConfigurationException(msg);
        }
        return securityManager;
    }

    private SecurityManager createSecurityManager(Ini ini) {
        return createSecurityManager(ini, getConfigSection(ini));
    }

    //獲取[main]的配置,如果沒(méi)得到則獲取默認(rèn)的配置
    private Ini.Section getConfigSection(Ini ini) {

        Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME);
        if (CollectionUtils.isEmpty(mainSection)) {
            //try the default:
            mainSection = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        return mainSection;
    }

    @SuppressWarnings({"unchecked"})
    private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) {
        /*
         * 注意,createDefaults被子類WebIniSecurityManagerFactory復(fù)寫(xiě),
         * 但其實(shí)也會(huì)首先調(diào)用本類的createDefaults方法,只是在結(jié)果中再添加了些默認(rèn)的Filter實(shí)例。
         * 
         * 然后將結(jié)果保存在ReflectionBuilder對(duì)象的objects【Map】屬性中,此時(shí)里面包含了默認(rèn)的SecurityManager、Realm以及各種默認(rèn)Filter實(shí)例;
         * 
         * 最后將createDefaults返回的Map全部加到ReflectionBuilder對(duì)象的objects【Map】中取緩存
         * */
        getReflectionBuilder().setObjects(createDefaults(ini, mainSection));

        //使用ReflectionBuilder構(gòu)建對(duì)象【創(chuàng)建實(shí)例對(duì)象,加入到objects變量中,然后執(zhí)行各個(gè)對(duì)象的init方法,同時(shí)返回objects對(duì)象】
        Map<String, ?> objects = buildInstances(mainSection);

        //直接從ReflectionBuilder對(duì)象中取出SecurityManager類型的對(duì)象
        SecurityManager securityManager = getSecurityManagerBean();

        /*
         * 如果securityManager不為RealmSecurityManager類型則返回true;
         * 如果是RealmSecurityManager類型,但是里面沒(méi)有Realm實(shí)例,返回為true;
         * 否則返回false
         * */
        boolean autoApplyRealms = isAutoApplyRealms(securityManager);

        if (autoApplyRealms) {
            //篩選其中的Realms對(duì)象【Realm或RealmFactory類型】
            Collection<Realm> realms = getRealms(objects);

            if (!CollectionUtils.isEmpty(realms)) {
                //如果securityManager不是RealmSecurityManager類型則拋出異常,否則給securityManager設(shè)置Realms
                applyRealmsToSecurityManager(realms, securityManager);
            }
        }
        return securityManager;
    }
}

到此,SecurityManager實(shí)例創(chuàng)建完成,并設(shè)置到IniWebEnvironment的屬性objects[Map]中

public class IniWebEnvironment extends ResourceBasedWebEnvironment implements Initializable, Destroyable {
    protected void configure() {

        //Map<String, Object>對(duì)象
        this.objects.clear();

        WebSecurityManager securityManager = createWebSecurityManager();
        setWebSecurityManager(securityManager);

        //獲取shiro.ini文件中配置的'filters' 或 'urls'項(xiàng)的Filter,加入objects對(duì)象中
        FilterChainResolver resolver = createFilterChainResolver();
        if (resolver != null) {
            setFilterChainResolver(resolver);
        }
    }
}

到此,Shiro的初始化過(guò)程完成,在EnvironmentLoaderListener 中將會(huì)把該IniWebEnvironment對(duì)象保存在ServletContext下供后面使用。

大致流程總結(jié)

系統(tǒng)啟動(dòng)的時(shí)候執(zhí)行EnvironmentLoaderListener初始化方法并創(chuàng)建WebEnvironment實(shí)例,同時(shí)將實(shí)例對(duì)象保存到ServletContext中

1,創(chuàng)建WebEnvironment對(duì)象
1)讀取web.xml中的上下文參數(shù)shiroEnvironmentClass
2)通過(guò)ServiceLoader方式查找jar包中的配置
3)是用默認(rèn)的IniWebEnvironment類型

2,調(diào)用WebEnvironment的init方法初始化WebEnvironment實(shí)例
注:WebEnvironment構(gòu)造犯法里面會(huì)創(chuàng)建WebIniSecurityManagerFactory實(shí)例factory。
1)從指定或默認(rèn)的路徑下解析shiro.ini文件生成Ini實(shí)例
2)將Ini實(shí)例設(shè)置給factory的ini屬性
3)將默認(rèn)的IniFilterChainResolverFactory設(shè)置給factory的defaultBeans(Map)屬性
4)調(diào)用factory的getInstance方法創(chuàng)建SecurityManager對(duì)象
--解析Ini對(duì)象里面的信息,創(chuàng)建Realm等對(duì)象并設(shè)置給SecurityManager實(shí)例
5)將SecurityManager返回的objects(Map)添加到WebEnvironment的objects中。

默認(rèn)的SecurityManager: DefaultWebSecurityManager

后面講接著介紹Session和Realm的使用

網(wǎng)站標(biāo)題:ApacheShiro源碼解讀之SecurityManager的創(chuàng)建
瀏覽地址:http://chinadenli.net/article44/iigiee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站電子商務(wù)網(wǎng)站導(dǎo)航搜索引擎優(yōu)化外貿(mào)網(wǎng)站建設(shè)網(wǎng)站設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管