Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The creation of SecurityManager for Apache Shiro Source Code interpretation

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

For the creation of SecurityManager for Shiro (v1.2 +), it can generally be created in the main method in ordinary applications.

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

This method reads the shiro.ini file under the classpath path to build the SecurityManager, but in the web application, how it is created is analyzed step by step.

In the web environment, we will use the following Listener, and the creation of the SecurityManager is during the initialization of the Listener [the Listener is in the shrio-web.jar]

Org.apache.shiro.web.env.EnvironmentLoaderListener

The inheritance relationship of EnvironmentLoaderListener is simple, as follows

The role of EnvironmentLoader is to load the Shiro when the application starts and to set the org.apache.shiro.web.mgt.WebSecurityManager to the ServletContext.

During the initialization of Shiro, the context parameters "shiroEnvironmentClass" and "shiroConfigLocations" configured in the web.xml file can guide the initialization process of Shiro. Of course, these two parameters are not required to be configured and have default values.

ShiroEnvironmentClass: develop a custom class that inherits from WebEnvironment, and the default object is IniWebEnvironment.

ShiroConfigLocations: specify the configuration file path to be used for shiro initialization. By default, / WEB-INF/shiro.ini will be queried first, and then classpath:shiro.ini will be found if it is not found.

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) {/ / find the WebEnvironment object and instantiate it 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; / / Save the current ServletContext object environment.setServletContext (sc) / / if the path to the configuration file is set in web.xml, then if (configSpecified & & (environment instanceof ResourceConfigurable)) {((ResourceConfigurable) environment) .setConfigLocations (configLocations) in environment is set here;} / / the constructor is not implemented by default customizeEnvironment (environment); / / call the init method of environment to initialize the environment object LifecycleUtils.init (environment) Return environment;} protected WebEnvironment determineWebEnvironment (ServletContext servletContext) {/ / get the configuration of WebEnvironment from the parameters of ServletContext-shiroEnvironmentClass. If there is an instance, return Class beans = factory.getBeans (); if (! CollectionUtils.isEmpty (beans)) {this.objects.putAll (beans);} return wsm;}}

Let's take a look at the implementation of WebIniSecurityManagerFactory's getInstance method.

As can be seen from the figure, when the getInstance method is called, the getInstance method located in AbstractFactory is actually executed

Public abstract class AbstractFactory implements Factory {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;} / * * subclass (IniFactorySupport) implements the process of creating instance * * / protected abstract T createInstance () } public abstract class IniFactorySupport extends AbstractFactory {public T createInstance () {/ * * get the Ini object, which has been set up earlier. * if the ini object does not exist, the Ini object is also created from the default path * * / Ini ini = resolveIni (); T instance; if (CollectionUtils.isEmpty (ini)) {/ / if the Ini object does not exist, the transfer subclass (IniSecurityManagerFactory) uses the default SecurityManager instance object 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 +"] "); / / call the subclass (IniSecurityManagerFactory) to build the SecurityManager object instance = createInstance (ini) based on the information of the SecurityManager object 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 {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 ();} / / default SecurityManager object [is actually overridden by WebIniSecurityManagerFactory and returns DefaultWebSecurityManager] protected SecurityManager createDefaultInstance () {return new DefaultSecurityManager () } / / create the SecurityManager object 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) according to Ini } return securityManager;} private SecurityManager createSecurityManager (Ini ini) {return createSecurityManager (ini, getConfigSection (ini));} / / get the configuration of [main], if not, get the default configuration 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) {/ * * Note that the createDefaults subclass WebIniSecurityManagerFactory is overridden, * but actually the createDefaults method of this class is called first, but some default Filter instances are added to the result. * * then save the result in the object [Map] property of the ReflectionBuilder object, which contains the default SecurityManager, Realm, and various default Filter instances * * finally, add all the Map returned by createDefaults to the objects [Map] of the ReflectionBuilder object to take the cache * * / getReflectionBuilder () .setObjects (createDefaults (ini, mainSection)); / / use ReflectionBuilder to build the object [create an instance object, add it to the objects variable, then execute the init method of each object, and return the objects object] Map objects = buildInstances (mainSection) / / fetch an object of type SecurityManager SecurityManager securityManager = getSecurityManagerBean () directly from the ReflectionBuilder object; / * * return true if securityManager is not of type RealmSecurityManager * if it is a RealmSecurityManager type, but there is no Realm instance in it, return true. * otherwise, return false * * / boolean autoApplyRealms = isAutoApplyRealms (securityManager); if (autoApplyRealms) {/ / filter the Realms object [Realm or RealmFactory type] Collection realms = getRealms (objects) If (! CollectionUtils.isEmpty (realms)) {/ / throw an exception if securityManager is not of type RealmSecurityManager, otherwise set Realms applyRealmsToSecurityManager (realms, securityManager) for securityManager;}} return securityManager;}}

At this point, the SecurityManager instance is created and set to the property objects [Map] of IniWebEnvironment

Public class IniWebEnvironment extends ResourceBasedWebEnvironment implements Initializable, Destroyable {protected void configure () {/ / Map object this.objects.clear (); WebSecurityManager securityManager = createWebSecurityManager (); setWebSecurityManager (securityManager); / / get the Filter of the 'filters' or' urls' entry configured in the shiro.ini file, and add FilterChainResolver resolver = createFilterChainResolver () to the objects object; if (resolver! = null) {setFilterChainResolver (resolver) }}}

At this point, the initialization process of Shiro is complete, and the IniWebEnvironment object will be saved under ServletContext in EnvironmentLoaderListener for later use.

General process summary

When the system starts, the EnvironmentLoaderListener initialization method is executed and the WebEnvironment instance is created, and the instance object is saved to ServletContext

1, create a WebEnvironment object

1) read the context parameter shiroEnvironmentClass in web.xml

2) find the configuration in the jar package by ServiceLoader

3) use the default IniWebEnvironment type

2. Call the init method of WebEnvironment to initialize the WebEnvironment instance

Note: the WebIniSecurityManagerFactory instance factory will be created in the WebEnvironment construction violation.

1) generate Ini instances by parsing shiro.ini files from the specified or default path

2) set the Ini instance to the ini property of factory

3) set the default IniFilterChainResolverFactory to the defaultBeans (Map) property of factory

4) call the getInstance method of factory to create a SecurityManager object

Parse the information in the Ini object, create objects such as Realm, and set them to the SecurityManager instance

5) add the objects (Map) returned by SecurityManager to the objects of WebEnvironment.

Default SecurityManager: DefaultWebSecurityManager

Later, we will introduce the use of Session and Realm.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report