当前位置: 首页 > 编程日记 > 正文

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源码学习之二

相关文章:

传百度要与阿里、腾讯争夺在线办公市场?“百度Hi”开放520人同时在线音视频会议

在线办公市场持续火热。4月20日&#xff0c;百度旗下在线办公平台“百度Hi”再升级&#xff0c;正式发布业内大规模的520人音视频会议&#xff0c;并支持多入口快速入会&#xff0c;加码在线办公。另有消息称&#xff0c;4月底&#xff0c;百度在线办公平台将发布重磅升级&…

SQL 2008 安装资料及下载地址

SQL Server 2008 序列号&#xff1a; Developer: PTTFM-X467G-P7RH2-3Q6CG-4DMYB Enterprise: JD8Y6-HQG69-P9H84-XDTPG-34MBB 服务器设置SQL Server 代理 NT AUTHORITY\SYSTEMSQL Server Database Engine NT AUTHORITY\NETWORK SERVICE SQL Server Browser 默认 SQL Ser…

Objective-C非正式协议与正式协议

为什么80%的码农都做不了架构师&#xff1f;>>> 类别与类扩展的区别&#xff1a; ①类别中只能增加方法&#xff1b; ②是的&#xff0c;你没看错&#xff0c;类扩展不仅可以增加方法&#xff0c;还可以增加实例变量&#xff08;或者合成属性&#xff09;&#xff…

Shiro源码学习之二

接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws AuthenticationException {clearRunAsIdentitiesInternal();Subject subject securityManager.login(this, token);PrincipalCollection principals;String hos…

Widgets 整理

1.滑动条 http://www.newnaw.com/pub/sl/031.html <--!grid中的内容--> <Grid x:Name"slidergrid" HorizontalAlignment"Left" VerticalAlignment"Center" Background"Azure" Margin"20"> <StackPane…

黑客用上机器学习你慌不慌?这 7 种窃取数据的新手段快来认识一下!

作者 | IrrfanAk译者 | 天道酬勤、Carol 责编 | Carol出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;机器学习以分析大型数据集和模式识别的能力而闻名。它基本上属于人工智能的一个子集。而机器学习使用的算法&#xff0c;是利用了先前的数据集和统计分析来做出假设…

ServletResponse-中文名的下载

2019独角兽企业重金招聘Python工程师标准>>> package com.httpServletResponse; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.se…

Linux环境编译安装OpenJDK

Centos6.5 AMD64位机器 Java的源码是C,C和Java实现的&#xff0c;所以还需要有一个安装好的java建议选OracleJDK参考文末 安装OracleJDK Linux环境安装卸载JDK以及安装Tomcat和发布Java的web程序 安装依赖 | Install dependence # yum -y install gcc gcc-c alsa-lib alsa-…

最快69秒逆向DRAM地址映射,百度设计的这款逆向工具如何做到快速可靠?

来源 | 百度安全实验室出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;导读&#xff1a;近日&#xff0c;国际顶级设计自动化大会DAC大会公布DAC 2020会议议程和论文名单&#xff0c;由百度安全发表的《DRAMDig: AKnowledge-assisted Tool to Uncover DRAM Address M…

国外厂商在行业客户上输单的原因

这两天听一个朋友聊天发泄&#xff0c;他在一家总代J公司工作&#xff0c;代理业内排行第一的国外厂商C公司的产品&#xff0c;他负责D行业在南方某几个省的销售业务&#xff0c;工作中需要与C公司的销售紧密配合。经过接近一年的工作&#xff0c;他拿到一些项目&#xff0c;但…

[android] 从gallery获取图片

效果就是点击按钮&#xff0c;打开系统图库应用&#xff0c;可以选择一张里面的图片展示出来 设置隐式意图 获取Intent对象&#xff0c;通过new出来 调用Intent对象的setAction()方法&#xff0c;设置动作&#xff0c;参数&#xff1a;Intent.ACTION_PICK 调用Intent对象的setT…

调试JDK源码-HashSet实现原理

调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hashtable实现原理以及线程安全的原因 代码 Set<String> snew HashSet<String>();s.add("http://blog.csdn.ne…

Python 炫技操作:海象运算符的三种用法

作者 | 明哥来源 | Python编程时光&#xff08;ID:Cool-Python&#xff09;Python 版本发展非常快&#xff0c;如今最新的版本已经是 Pyhton 3.9&#xff0c;即便如此&#xff0c;有很多人甚至还停留在 3.6 或者 3.7&#xff0c;连 3.8 还没用上。很多 Python 3.8 的特性还没来…

2010.10.30 OA 项目组一周工作报告

本周基本上实现了上周的目标&#xff0c;但和计划相比有落后。 进度&#xff1a;55 本周提交了3.0任务评估的第一个版本&#xff0c;一共为1003小时&#xff0c;客户收到该评估后&#xff0c;对3.0任务进行了调整&#xff0c;将部分任务移到2011.2版本中&#xff0c;同时添加了…

继承log4.net的类

using System; using System.Diagnostics;[assembly: log4net.Config.XmlConfigurator(Watch true)] namespace Hbl.Core {public static class Log{/// <summary>/// 一般错误/// </summary>/// <param name"message">消息</param>public …

调试JDK源码-Hashtable实现原理以及线程安全的原因

调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hashtable实现原理以及线程安全的原因 Hashtable是线程安全的&#xff0c;我们从源码来分析 代码很简单 Hashtable<String, …

源代码查看工具 Source Navigator 使用心得

在ubuntu 10.04下试用了Source Navigator&#xff0c;有条件还是装Source insight吧&#xff0c;不是一个级别的&#xff0c;非常不方便。 Source Navigator 是Red Hat出品的一款查看源代码的工具&#xff0c;非常好用&#xff0c;与Windows下的Source Insight有一敌。但是它的…

那个分分钟处理10亿节点图计算的Plato,现在怎么样了?

受访者 | 于东海记者 | 夕颜出品 | CSDN&#xff08;ID:CSDNnews&#xff09;「AI 技术生态论」 人物访谈栏目是 CSDN 发起的百万人学 AI 倡议下的重要组成部分。通过对 AI 生态顶级大咖、创业者、行业 KOL 的访谈&#xff0c;反映其对于行业的思考、未来趋势的判断、技术的实践…

android TextView里边实现图文混配效果

做的游戏攻略中的图文载入已经用TextView实现。但看到网易新闻里的内容。点击图片能够调到一个新的Activity &#xff0c;感觉也像Textview 实现的&#xff0c;但不知道怎么弄&#xff0c;想想能够通过动态载入Textview和ImageView 布局实现&#xff0c;但当量大的时候回事很复…

《异步处理在分布式系统中的优化作用》学习笔记

原文地址&#xff1a;http://www.infoq.com/cn/presentations/optimization-of-asynchronous-processing-in-distributed-systems 视频地址&#xff1a;http://v.qq.com/boke/page/l/0/6/l0196plsvp6.html 主讲人&#xff1a;赵海平 Facebook hiphop HHVM 阿里巴巴技术保障部…

CISCO设备上DHCP实例

Cisco设备上设置DHCP实例 -------------------------------------------------------------------------------- 一位客户想把DHCP SERVER迁移到6509交换机的MSFC上,要求还挺复杂: 1.同时为多个VLAN的客户机分配地址 2.VLAN内有部分地址采用手工分配的…

360金融翟政:科技成就金融场景零容错

翟政&#xff0c;拥有超过20年的互联网经验&#xff0c;我国第三方支付第一批从业者&#xff0c;是多个知名第三方支付公司产品研发团队的组建者&#xff0c;核心系统的主设计师&#xff0c;管理层核心成员。设计搭建的支付系统过去这十年来一直在服务着各行各业的在线支付需求…

OSSIM平台安全事件关联分析实践

OSSIM平台安全事件关联分析实践在《开源安全运维平台OSSIM最佳实践》一书中叙述到&#xff0c;事件关联是整个OSSIM关联分析的核心&#xff0c;对于OSSIM的事件关联需要海量处理能力&#xff0c;主要便于现在需要及时存储从设备采集到的日志&#xff0c;并能关联匹配和输出&…

《Apache Kafka》学习笔记

1.什么是Kafka Kafka是一个高通过率的分布式消息系统 2.消息队列&#xff08;Message Queue)MQ的模型 消息队列的简单架构图 3个核心概念&#xff1a; Sender Application&#xff1a;消息队列的发送者&#xff0c;也叫生产者producer Message Queue Receiver Application…

4 月 24 日开播!基于神经网络建模的信息传播预测

信息传播在我们的日常生活中无处不在&#xff0c;例如谣言的扩散、产品的推广以及新思想和新技术的普及等等&#xff0c;其建模和预测已经在多个重要领域内得到了广泛的研究。近年来&#xff0c;很多研究者利用以循环神经网络为主的深度学习模型对信息传播过程进行建模&#xf…

并行计算圆周率

看到这个题目&#xff0c;俗了&#xff0c;大家都在计算圆周率。不过咱们的目的是看一下并行计算的基本流程。 书上计算PI用的是精确的数值计算方法&#xff0c;我这里再给出一种概率计算方法。 OpenMP和MPI将同时亮相。 计算PI的方法 1.tan(PI/4)1 > PI4arctan1。知…

kafka-manager 的编译和使用(附安装包)

2019独角兽企业重金招聘Python工程师标准>>> kafka-manager是一个非常好用的kafka web管理工具&#xff0c;yahoo开源。 地址&#xff1a;github.com/yahoo/kafka-manager 1、编译过程比较简单&#xff0c;重点是能翻墙&#xff0c;如果网络环境不允许&#xff0c;可…

匿名函数应用-多线程测试代码

多线程测试代码&#xff0c;不用单独再写一个类&#xff0c;比较方面而已。 public class MainThread { static int a0; for (int x 0;x<100;x){ Thread t new Thread(new Runnable() { Override public void run() { while(true){ try { a;System.out.println(a);…

YOLOv4来了,大型调优现场,速度和准确率俱佳

作者 | VincentLee来源 | 晓飞的算法工程笔记简介论文提出YOLOv4&#xff0c;从图1的结果来看&#xff0c;相对于YOLOv3在准确率上提升了近10个点&#xff0c;然而速度并几乎没有下降&#xff0c;论文主要贡献如下&#xff1a;提出速度更快、精度更好的检测模型&#xff0c;仅需…

关于对J2EE几点误解和错误认识的澄清

转自&#xff1a;http://www.jdon.com .Net和J2EE的争论一直没有停止&#xff0c;我也参加过“程序员”杂志主持的“.Net和Java之争”之类的讨论&#xff0c;本来这两种技术都是为用户提供了竞争性的选择&#xff0c;对于用户来说是一件好事&#xff0c;多种选择远胜于单一选择…