鲁春利的工作笔记,好记性不如烂笔头
1、Shiro配置文件(first-shiro.ini)
[users] lucl=123 wang=123
2、单元测试类
@Test public void testLoginWithNoGivenRealm () { // 1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro/first-shiro.ini"); // 2、得到SecurityManager实例并绑定给SecurityUtils org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); // org.apache.shiro.mgt.DefaultSecurityManager logger.info("security manager is " + securityManager + "."); SecurityUtils.setSecurityManager(securityManager); // 3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("lucl", "123"); try{ // 4、登录,即身份验证 subject.login(token); } catch (AuthenticationException e) { // 5、身份验证失败 logger.info("用户身份验证失败"); e.printStackTrace(); } Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录 if (subject.isAuthenticated()) { logger.info("用户登录成功。"); } else { logger.info("用户登录失败。"); } // 6、退出 subject.logout(); }
3、过程分析
3.1、获取SecurityManager工厂
-
new IniSecurityManagerFactory(“classpath:shiro/first-shiro.ini”);
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文件路径),然后会调用IniSecurityManagerFactory(Ini config) public IniSecurityManagerFactory(String iniResourcePath) { this(Ini.fromResourcePath(iniResourcePath)); } // 略 }
-
setIni(config);
调用IniFactorySupport类的setIni方法
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 Ini ini; protected IniFactorySupport() { } protected IniFactorySupport(Ini ini) { this.ini = ini; } public Ini getIni() { return ini; } public void setIni(Ini ini) { this.ini = ini; } }
3.2、得到SecurityManager实例并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
-
factory.getInstance();调用AbstractFactory的getInstance()方法
package org.apache.shiro.util; /** * TODO - Class JavaDoc * * @since 1.0 */ public abstract class AbstractFactory<T> implements Factory<T> { private boolean singleton; private T singletonInstance; // 无参构造方法,默认会被容器加载,因此singleton标识默认为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 if (this.singletonInstance == null) { // 调用createInstance方法 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)的实现 protected abstract T createInstance(); }
-
调用子类(IniFactorySupport)的createInstance()
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、获取ini指定的配置文件(resolveIni会调用getIni,读取之前setIni时的值); * 2、若ini为空通过createDefaultInstance()方法创建默认的实例(default instance);否则基于ini创建实例(createInstance(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) { // 异常信息略 throw new IllegalStateException(msg); } } else { log.debug("Creating instance from Ini [" + ini + "]"); instance = createInstance(ini); if (instance == null) { // 异常信息略 throw new IllegalStateException(msg); } } return instance; } // 为抽象方法,需要调用其实现类的createInstance(Ini ini)方法 protected abstract T createInstance(Ini ini); // 为抽象方法,需要调用其实现类的createDefaultInstance()方法 protected abstract T createDefaultInstance(); }
-
IniSecurityManagerFactory类的createDefaultInstance()
public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> { protected SecurityManager createDefaultInstance() { return new DefaultSecurityManager(); } }
-
IniSecurityManagerFactory类的createInstance(Ini ini)
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."); } // 最核心的是createSecurityManager方法 SecurityManager securityManager = createSecurityManager(ini); if (securityManager == null) { String msg = SecurityManager.class + " instance cannot be null."; throw new ConfigurationException(msg); } return securityManager; } }
-
IniSecurityManagerFactory类的createSecurityManager(Ini ini)方法
public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> { private SecurityManager createSecurityManager(Ini ini) { 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); } // 中间代码略 @SuppressWarnings({"unchecked"}) private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) { // 实际上获取到SecurityManager的地方是在createDefaults Map<String, ?> defaults = createDefaults(ini, mainSection); // buildInstances实际上是ReflectionBuilder对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; } // 转了一圈还是调用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; } }