日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Shiro源码学习之一

發布時間:2023/11/27 生活经验 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Shiro源码学习之一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.最基本的使用


1.Maven依賴

        <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.2.4</version></dependency><dependency>  <groupId>org.slf4j</groupId>  <artifactId>slf4j-api</artifactId>  <version>1.7.13</version>  </dependency>  <dependency>  <groupId>org.slf4j</groupId>  <artifactId>slf4j-log4j12</artifactId>  <version>1.7.13</version>  </dependency>

2.配置文件

[users]
user1 = http://blog.csdn.net/unix21
admin1 = 11111


3.調用代碼
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class HelloShiro {private static final Logger logger =  LoggerFactory.getLogger(HelloShiro.class);public static void main(String[] args) {// 初始化 SecurityManagerFactory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();SecurityUtils.setSecurityManager(securityManager);// 獲取當前用戶Subject subject = SecurityUtils.getSubject();// 登錄UsernamePasswordToken token = new UsernamePasswordToken("user1", "http://blog.csdn.net/unix21");try {subject.login(token);} catch (AuthenticationException ae) {logger.info("登錄失敗!");return;}logger.info("登錄成功!Hello " + subject.getPrincipal());// 注銷subject.logout();}
}


參考:Shiro 那點事兒

跟我學Shiro目錄貼


二.源碼學習

1.SecurityManager

SecurityManager securityManager = factory.getInstance();


進入public T getInstance()


進入public T createInstance()

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;}


進入protected Ini resolveIni()
protected Ini resolveIni() {Ini ini = getIni();if (CollectionUtils.isEmpty(ini)) {log.debug("Null or empty Ini instance.  Falling back to the default {} file.", DEFAULT_INI_RESOURCE_PATH);ini = loadDefaultClassPathIni();}return ini;}


public Ini getIni()


ini是一個自定義的Class

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 sectionpublic 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>();}

跳出protected Ini resolveIni()

回到public T createInstance()



進入protected SecurityManager createInstance(Ini ini)



進入public Section getSection(String sectionName)



進入private static String cleanName(String sectionName)

private static String cleanName(String sectionName) {String name = StringUtils.clean(sectionName);if (name == null) {log.trace("Specified name was null or empty.  Defaulting to the default section (name = \"\")");name = DEFAULT_SECTION_NAME;}return name;}


org.apache.shiro.util的StringUtils


EMPTY_STRING是StringUtils定義的靜態常量

public class StringUtils {public static final String EMPTY_STRING = "";public static final char DEFAULT_DELIMITER_CHAR = ',';public static final char DEFAULT_QUOTE_CHAR = '"';
out返回"main"


private static String cleanName(String sectionName)返回"main"



回到public Section getSection(String sectionName)


ini.getSection返回null回到private SecurityManager createSecurityManager(Ini ini)


又到public Section getSection(String sectionName)返回null

public Section getSection(String sectionName) {String name = cleanName(sectionName);return sections.get(name);}

回到private SecurityManager createSecurityManager(Ini ini)


進入createSecurityManager

@SuppressWarnings({"unchecked"})private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) {Map<String, ?> defaults = createDefaults(ini, mainSection);Map<String, ?> objects = buildInstances(mainSection, defaults);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 SecurityManagerif (!CollectionUtils.isEmpty(realms)) {applyRealmsToSecurityManager(realms, securityManager);}}return securityManager;}


進入createDefaults

    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);if (shouldImplicitlyCreateRealm(ini)) {Realm realm = createRealm(ini);if (realm != null) {defaults.put(INI_REALM_NAME, realm);}}return defaults;}


protected SecurityManager createDefaultInstance() {return new DefaultSecurityManager();}
public DefaultSecurityManager() {super();this.subjectFactory = new DefaultSubjectFactory();this.subjectDAO = new DefaultSubjectDAO();}
public SessionsSecurityManager() {super();this.sessionManager = new DefaultSessionManager();applyCacheManagerToSessionManager();}
public AuthorizingSecurityManager() {super();this.authorizer = new ModularRealmAuthorizer();}
public AuthenticatingSecurityManager() {super();this.authenticator = new ModularRealmAuthenticator();}
public RealmSecurityManager() {super();}
最終是個空方法

public abstract class CachingSecurityManager implements SecurityManager, Destroyable, CacheManagerAware {private CacheManager cacheManager;public CachingSecurityManager() {}


...之后
回到createDefaults


protected boolean shouldImplicitlyCreateRealm(Ini ini)

protected boolean shouldImplicitlyCreateRealm(Ini ini) {return !CollectionUtils.isEmpty(ini) &&(!CollectionUtils.isEmpty(ini.getSection(IniRealm.ROLES_SECTION_NAME)) ||!CollectionUtils.isEmpty(ini.getSection(IniRealm.USERS_SECTION_NAME)));}

回到createDefaults進入createRealm


IniRealm聲明

public class IniRealm extends TextConfigurationRealm {public static final String USERS_SECTION_NAME = "users";public static final String ROLES_SECTION_NAME = "roles";private static transient final Logger log = LoggerFactory.getLogger(IniRealm.class);private String resourcePath;private Ini ini; //reference added in 1.2 for SHIRO-322public IniRealm() {super();}

調用super()的super()



實例化LinkedHashMap和讀寫鎖ReadWriteLock


回到createRealm


回到createDefaults


回到createSecurityManager


進入buildInstances

private Map<String, ?> buildInstances(Ini.Section section, Map<String, ?> defaults) {this.builder = new ReflectionBuilder(defaults);return this.builder.buildObjects(section);}

進入ReflectionBuilder



這行代碼很簡潔,defaults不為空,所以this.objects指向defaults的引用

this.objects = CollectionUtils.isEmpty(defaults) ? new LinkedHashMap<String, Object>() : defaults;



進入buildObjects 因為kvPairs為null所以直接跳到LifecycleUtils.init(objects.values());




再跳到public static void init(Object o),判斷對象不能Initializable



第二次又進入這次對象是可以Initializable


進入

public final void init() {//trigger obtaining the authorization cache if possiblegetAvailableAuthenticationCache();onInit();}

進入getAvailableAuthenticationCache

private Cache<Object, AuthenticationInfo> getAvailableAuthenticationCache() {Cache<Object, AuthenticationInfo> cache = getAuthenticationCache();boolean authcCachingEnabled = isAuthenticationCachingEnabled();if (cache == null && authcCachingEnabled) {cache = getAuthenticationCacheLazy();}return cache;}
返回是null


回到

public final void init() {//trigger obtaining the authorization cache if possiblegetAvailableAuthenticationCache();onInit();}


進入onInit()
@Overrideprotected void onInit() {super.onInit();// This is an in-memory realm only - no need for an additional cache when we're already// as memory-efficient as we can be.Ini ini = getIni();String resourcePath = getResourcePath();if (!CollectionUtils.isEmpty(this.users) || !CollectionUtils.isEmpty(this.roles)) {if (!CollectionUtils.isEmpty(ini)) {log.warn("Users or Roles are already populated.  Configured Ini instance will be ignored.");}if (StringUtils.hasText(resourcePath)) {log.warn("Users or Roles are already populated.  resourcePath '{}' will be ignored.", resourcePath);}log.debug("Instance is already populated with users or roles.  No additional user/role population " +"will be performed.");return;}if (CollectionUtils.isEmpty(ini)) {log.debug("No INI instance configuration present.  Checking resourcePath...");if (StringUtils.hasText(resourcePath)) {log.debug("Resource path {} defined.  Creating INI instance.", resourcePath);ini = Ini.fromResourcePath(resourcePath);if (!CollectionUtils.isEmpty(ini)) {setIni(ini);}}}if (CollectionUtils.isEmpty(ini)) {String msg = "Ini instance and/or resourcePath resulted in null or empty Ini configuration.  Cannot " +"load account data.";throw new IllegalStateException(msg);}processDefinitions(ini);}


super.onInit()也就是protected void onInit()

@Overrideprotected void onInit() {super.onInit();processDefinitions();}


processDefinitions調用processRoleDefinitions(),roleDefinitions為null直接返回到processDefinitions


processUserDefinitions中userDefinitions也是null直接return回processDefinitions了




回到onInit()

返回



返回



回到buildObjects返回objects



回到buildInstances



回到createSecurityManager


private SecurityManager getSecurityManagerBean() {return builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class);}


進入org.apache.shiro.config的public class ReflectionBuilder



instanceof運算符 只被用于對象引用變量,檢查左邊的被測試對象 是不是 右邊類或接口的 實例化。如果被測對象是null值,則測試結果總是false。?
Class類的isInstance(Object obj)方法,obj是被測試的對象,如果obj是調用這個方法的class或接口 的實例,則返回true。這個方法是instanceof運算符的動態等價。?
Class類的isAssignableFrom(Class cls)方法,如果調用這個方法的class或接口 與 參數cls表示的類或接口相同,或者是參數cls表示的類或接口的父類,則返回true。?

instanceof, isinstance,isAssignableFrom的區別


回到createSecurityManager



進入isAutoApplyRealms


realms為null,返回autoApply為true


回到createSecurityManager



進入applyRealmsToSecurityManager


再調用setRealms



回到protected void afterRealmsSet()



回到setRealms


回到


回到


回到


回到


回到


回到



回到最外層調用函數


至此,SecurityManager securityManager = factory.getInstance();才完成。


2.Subject

// 獲取當前用戶Subject subject = SecurityUtils.getSubject();


public static Subject getSubject() {Subject subject = ThreadContext.getSubject();if (subject == null) {subject = (new Subject.Builder()).buildSubject();ThreadContext.bind(subject);}return subject;}


進入org.apache.shiro.util的public abstract class ThreadContext?


getValue



回到public static Subject getSubject()



回到最外層



3.UsernamePasswordToken

UsernamePasswordToken token = new UsernamePasswordToken("user1", "http://blog.csdn.net/unix21");





調用構造函數



private聲明
public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
private String username;
private char[] password;
private boolean rememberMe = false;
private String host;
...


HostAuthenticationToken接口定義

public interface HostAuthenticationToken extends AuthenticationToken {
String getHost();
}public interface AuthenticationToken extends Serializable {
Object getPrincipal();
Object getCredentials();
}

Shiro源碼學習之二

總結

以上是生活随笔為你收集整理的Shiro源码学习之一的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。