生成安全管理器 冷不防 2022-05-21 01:28 153阅读 0赞 * 生成安全管理器 * 初始化安全管理器工厂 * 获得ini对象 * 设置ini对象 * 获取安全管理器实例 * createSecurityManager * createDefault * buildInstances * getSecurityManagerBean * applyRealmsToSecurityManager * initRealm * 生命周期初始化 * 总结 * 设置全局安全管理器对象 * 附注 * 加入新节区对象 * 参考资料 # 生成安全管理器 # @Before public void beforeInitial() { Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); } 这里做了三件事 1. 初始化安全管理器工厂 2. 获取安全管理器实例 3. 设置全局安全管理器对象 ## 初始化安全管理器工厂 ## ### 获得ini对象 ### ![IniSecurityManagerFactory 时序图][IniSecurityManagerFactory] > new IniSecurityManagerFactory(“classpath:shiro.ini”); IniSecurityManagerFactory public IniSecurityManagerFactory(String iniResourcePath) { this(Ini.fromResourcePath(iniResourcePath)); } > this(Ini.fromResourcePath(iniResourcePath)); 载入ini资源 Ini public static Ini fromResourcePath(String resourcePath) throws ConfigurationException { if (!StringUtils.hasLength(resourcePath)) { throw new IllegalArgumentException("Resource Path argument cannot be null or empty."); } Ini ini = new Ini(); ini.loadFromPath(resourcePath); return ini; } > ini.loadFromPath(resourcePath); public void loadFromPath(String resourcePath) throws ConfigurationException { InputStream is; try { is = ResourceUtils.getInputStreamForPath(resourcePath); } catch (IOException e) { throw new ConfigurationException(e); } load(is); } **价值** ★★★☆ getInputStreamForPath shiro载入配置文件的多种方式: 1. `classpath:` 开头 2. `url:` 开头 3. `file:` 开头 4. 默认从磁盘读取 读取失败就抛出异常 ResourceUtils public static InputStream getInputStreamForPath(String resourcePath) throws IOException { InputStream is; if (resourcePath.startsWith(CLASSPATH_PREFIX)) { is = loadFromClassPath(stripPrefix(resourcePath)); } else if (resourcePath.startsWith(URL_PREFIX)) { is = loadFromUrl(stripPrefix(resourcePath)); } else if (resourcePath.startsWith(FILE_PREFIX)) { is = loadFromFile(stripPrefix(resourcePath)); } else { is = loadFromFile(resourcePath); } if (is == null) { throw new IOException("Resource [" + resourcePath + "] could not be found."); } return is; } ### 设置ini对象 ### > this(Ini.fromResourcePath(iniResourcePath)); ![IniSecurityManagerFactory 类图][IniSecurityManagerFactory 1] 将 this.ini 设置为 获得的资源对象 调用父类 AbstractFactory构造,设置 this.singleton = true; public IniSecurityManagerFactory(Ini config) { setIni(config); } ## 获取安全管理器实例 ## ![IniSecurityManagerFactory 时序图][IniSecurityManagerFactory 2] 从时序图上面来看,我们要跟进到 createSecurityManager 寻找下面两个问题的答案 1. 如何创建 securityManager 2. 如何填充里面的用户和权限信息的 public T getInstance() { T instance; // 已经设置为 true if (isSingleton()) { // 初次使用为null if (this.singletonInstance == null) { // createInstance 为abstract ,将由子类实例化 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 实现了createInstance 获取this.ini的值,如果存在就根据ini创建Instance,否则创建默认的Instance. 创建失败就抛出 IllegalStateException 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() + " 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 + "]"); 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; } IniSecurityManagerFactory 本身实现 createInstance 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; } 创建安全管理器 获取节区 \[main\] ,获取失败就获取 ” 节区 private SecurityManager createSecurityManager(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 createSecurityManager(ini, mainSection); } ### createSecurityManager ### **价值** ★★★★★ 终于能看到返回 SecurityManager 的地方了 ,重中之中,配置信息都在这里加载 private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) { // 创建默认的securityManager 和 iniRealm 对象 Map<String, ?> defaults = createDefaults(ini, mainSection); // this.builder 初始化objects为 defaults // 实例化main节区的对象和填充属性 加入到builder 的objects 里面 Map<String, ?> objects = buildInstances(mainSection, defaults); // 从defaults(this.builder.objects对象引用的defaults) 里面获取 SecurityManager SecurityManager securityMana ger = getSecurityManagerBean(); //securityManager 是一个RealmSecurityManager,并且realms 不为空就为false // 查看: DefaultSecurityManager类图 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); } } // securityManager 里面的realms 是否实现了org.apache.shiro.util.Initializable,实现了就调用init方法 initRealms(securityManager); return securityManager; DefaultSecurityManager类图 ![DefaultSecurityManager类图][DefaultSecurityManager] ### createDefault ### **级别7** protected Map<String, ?> createDefaults(Ini ini, Ini.Section mainSection) { Map<String, Object> defaults = new LinkedHashMap<String, Object>(); // 创建DefaultSecurityManager SecurityManager securityManager = createDefaultInstance(); defaults.put(SECURITY_MANAGER_NAME, securityManager); // 验证ini是否为空,ini是否有[users]节区,[roles]节区 if (shouldImplicitlyCreateRealm(ini)) { Realm realm = createRealm(ini); if (realm != null) { defaults.put(INI_REALM_NAME, realm); } } return defaults; } ### buildInstances ### 这段内容很简单, , 做了下面两个步骤 1. 创建当前的构建器 this.builder 2. 构建目标节区对象,并返回 this.builder.objects. 在本例中 目标节区为null,所以不会加入新的对象, 可以通过加入新节区对象获取更多信息 private Map<String, ?> buildInstances(Ini.Section section, Map<String, ?> defaults) { this.builder = new ReflectionBuilder(defaults); return this.builder.buildObjects(section); } > this.builder = new ReflectionBuilder(defaults); 构造ReflectionBuilder时,设置成员变量 this.objects的值 ReflectionBuilder public ReflectionBuilder(Map<String, ?> defaults) { this.objects = CollectionUtils.isEmpty(defaults) ? new LinkedHashMap<String, Object>() : defaults; } ### getSecurityManagerBean ### 通过builder 获取 securityManager 对象 public static final String SECURITY_MANAGER_NAME = "securityManager"; private SecurityManager getSecurityManagerBean() { return builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class); } > return builder.getBean(SECURITY\_MANAGER\_NAME, SecurityManager.class); 可以看出来,实际上就是当前ReflectionBuilder的objects中获取一个key为securityManager的对象,在强转为目标对象 ReflectionBuilder public Object getBean(String id) { return objects.get(id); } public <T> T getBean(String id, Class<T> requiredType) { if (requiredType == null) { throw new NullPointerException("requiredType argument cannot be null."); } Object bean = getBean(id); if (bean == null) { return null; } if (!requiredType.isAssignableFrom(bean.getClass())) { throw new IllegalStateException("Bean with id [" + id + "] is not of the required type [" + requiredType.getName() + "]."); } return (T) bean; } **级别8** 根据创建Realm protected Realm createRealm(Ini ini) { IniRealm realm = new IniRealm(ini); realm.setName(INI_REALM_NAME); return realm; } IniRealm 类图: ![IniRealm类图][IniRealm] **级别9** public IniRealm(Ini ini) { this(); processDefinitions(ini); } **级别10** 1. 填充SimpleAccountRealm 的 Map private void processDefinitions(Ini ini) { if (CollectionUtils.isEmpty(ini)) { log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName()); return; } Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME); if (!CollectionUtils.isEmpty(rolesSection)) { log.debug("Discovered the [{}] section. Processing...", ROLES_SECTION_NAME); processRoleDefinitions(rolesSection); } Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME); if (!CollectionUtils.isEmpty(usersSection)) { log.debug("Discovered the [{}] section. Processing...", USERS_SECTION_NAME); processUserDefinitions(usersSection); } else { log.info("{} defined, but there is no [{}] section defined. This realm will not be populated with any " + "users and it is assumed that they will be populated programatically. Users must be defined " + "for this Realm instance to be useful.", getClass().getSimpleName(), USERS_SECTION_NAME); } } ### applyRealmsToSecurityManager ### 获取安全数据源集合 private Collection<Realm> getRealms(Map<String, ?> instances) { //realms and realm factory might have been created - pull them out first so we can //initialize the securityManager: List<Realm> realms = new ArrayList<Realm>(); //iterate over the map entries to pull out the realm factory(s): for (Map.Entry<String, ?> entry : instances.entrySet()) { String name = entry.getKey(); Object value = entry.getValue(); // 加入用户创建的realm if (value instanceof RealmFactory) { addToRealms(realms, (RealmFactory) value); } else if (value instanceof Realm) { // 加入iniRealm Realm realm = (Realm) value; //set the name if null: String existingName = realm.getName(); if (existingName == null || existingName.startsWith(realm.getClass().getName())) { if (realm instanceof Nameable) { ((Nameable) realm).setName(name); log.debug("Applied name '{}' to Nameable realm instance {}", name, realm); } else { log.info("Realm does not implement the {} interface. Configured name will not be applied.", Nameable.class.getName()); } } realms.add(realm); } } return realms; } 设置 securityManager 的 realms protected void applyRealmsToSecurityManager(Collection<Realm> realms, SecurityManager securityManager) { // 验证 securityManager!=null 并且 securityManager 必须是一个 RealmSecurityManager assertRealmSecurityManager(securityManager); ((RealmSecurityManager) securityManager).setRealms(realms); } > ((RealmSecurityManager) securityManager).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; // 依次调用父类的afterReamlSet afterRealmsSet(); } > afterRealmsSet(); AuthorizingSecurityManager 的 afterRealmsSet 第三个设置 this.authorizer 的realms protected void afterRealmsSet() { super.afterRealmsSet(); if (this.authorizer instanceof ModularRealmAuthorizer) { ((ModularRealmAuthorizer) this.authorizer).setRealms(getRealms()); } } AuthenticatingSecurityManager 的 afterRealmsSet 第二个设置 this.authenticator 的realms protected void afterRealmsSet() { super.afterRealmsSet(); if (this.authenticator instanceof ModularRealmAuthenticator) { ((ModularRealmAuthenticator) this.authenticator).setRealms(getRealms()); } } RealmSecurityManager 的 afterRealmsSet 第一个设置 realms里面每个Realm 的缓存管理器 protected void afterRealmsSet() { applyCacheManagerToRealms(); } 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); } } } } ### initRealm ### 初始化realm 做了什么呢? 1. 验证安全管理器 不为空 并且 必须是 RealmSecurityManager 或者子类对象 2. 获取 securityManager 的所有安全数据源 3. 调用生命周期工具的初始化 private Collection<Realm> getRealms(SecurityManager securityManager) { assertRealmSecurityManager(securityManager); return ((RealmSecurityManager) securityManager).getRealms(); } private void initRealms(SecurityManager securityManager) { Collection<Realm> realms = getRealms(securityManager); if (!CollectionUtils.isEmpty(realms)) { LifecycleUtils.init(realms); } } #### 生命周期初始化 #### > LifecycleUtils.init(realms); 从下面的代码可以看出来,实际上就是遍历集合,判断集合的每个元素是否实现了接口 Initializable. 如果实现了,就调用接口的init方法 // init((Initializable) o); public static void init(Initializable initializable) throws ShiroException { initializable.init(); } // init(o); public static void init(Object o) throws ShiroException { if (o instanceof Initializable) { init((Initializable) o); } } // LifecycleUtils.init(realms); public static void init(Collection c) throws ShiroException { if (c == null || c.isEmpty()) { return; } for (Object o : c) { init(o); } } ### 总结 ### 到这里为止,SecurityManager 就已经创建完成,里面的数据也依次填充完成了 ## 设置全局安全管理器对象 ## 设置 SecurityUtils 的静态变量securityManager SecurityUtils public static void setSecurityManager(SecurityManager securityManager) { SecurityUtils.securityManager = securityManager; } # 附注 # ## 加入新节区对象 ## # 参考资料 # [官网教程][Link 1] [IniSecurityManagerFactory]: https://gitee.com/ls9527/src-analysis/raw/master/shiro/uml/seq/IniSecurityManagerFactory.png [IniSecurityManagerFactory 1]: https://gitee.com/ls9527/src-analysis/raw/master/shiro/uml/class/IniSecurityManagerFactory.png [IniSecurityManagerFactory 2]: https://gitee.com/ls9527/src-analysis/raw/master/shiro/uml/seq/IniSecurityManagerFactory.getInstance.png [DefaultSecurityManager]: https://gitee.com/ls9527/src-analysis/raw/master/shiro/uml/class/DefaultSecurityManager.png [IniRealm]: https://gitee.com/ls9527/src-analysis/raw/master/shiro/uml/class/IniRealm.png [Link 1]: https://shiro.apache.org/tutorial.html
还没有评论,来说两句吧...