Shiro源码学习(一)Filter的创建

Shiro源码学习(三)常用Filter源码和继承关系 Filter类别Shiro为我们提供了默认的几种拦截器,并且也支持我们通过继承来编写我们自定义的拦截器。Shiro中默认的拦截器有:其含义如下:anon:例子/admins/**=anon 没有参数,表示可以匿名使用。 authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数 roles:例子/admins/user/**=roles[admin],参数可以... 阅读详情

一、从web.xml到Spring容器

我们在使用spring配置shiro时,有两处需要配置Filter相关的地方:

    <!-- Shiro配置 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping> 
    <!-- Shiro的Web过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 调用我们配置的权限管理器 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 配置我们的登录请求地址 -->
        <property name="loginUrl" value="/static/login.html"/>
        <!--<property name="loginUrl" value="/common/login"/>-->
        <!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 -->
        <property name="successUrl" value="/common/route"/>
        <!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
        <property name="unauthorizedUrl" value="/common/403"/>
        <property name="filters">
            <map>
                <entry key="ownauthc">
                    <!--自定义过滤器,方便ajax交互-->
                    <!--<ref bean="formAuthenticationFilter"/>-->
                    <ref bean="ownRoleAuthorizationFilter"></ref>
                </entry>
            </map>
        </property>
        <!-- 权限配置 -->
        <property name="filterChainDefinitions">
            <value>
                <!--/common/doLogin/user=ownauthc-->
                /common/**=anon
                /search/**=anon
                /static/superAdmin/**=roles[superadmin]
                /static/admin/**=roles[admin]
                /static/** = anon
            </value>
        </property>

    </bean>

其实真正发挥拦截器作用的只有Spring中配置的ShiroFilterFactoryBean,而web.xml中配置的拦截器DelegatingFilterProxy功能相当于是为Spring中的Filter做了一层包装, DelegatingFilterProxy相关的源码如下:

	@Override
	protected void initFilterBean() throws ServletException {
		synchronized (this.delegateMonitor) {
			if (this.delegate == null) {
				// If no target bean name specified, use filter name.
				if (this.targetBeanName == null) {
					//web.xml中配置的FilterName属性,当然也可以直接在web.xml中指定targetBeanName属性
					this.targetBeanName = getFilterName();
				}
				// Fetch Spring root application context and initialize the delegate early,
				// if possible. If the root application context will be started after this
				// filter proxy, we'll have to resort to lazy initialization.
				WebApplicationContext wac = findWebApplicationContext();//获取Spring容器的上下文对象(该方法调用由Spring提供的静态方法获取ApplicationContext容器对象)
				if (wac != null) {
					this.delegate = initDelegate(wac);//获取Spring配置文件中配置的拦截器,并作为其代理对象
				}
			}
		}
	}
	protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
		//获取Spring容器中beanName=targetBeanName,类型为Filter的bean
		Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
		if (isTargetFilterLifecycle()) {
			delegate.init(getFilterConfig());
		}
		return delegate;
	}

该方法是在Filter的初始化阶段调用,功能是对delegate属性赋初值:在Spring容器中获取到bean名和filter-name属性值相同的bean,delegate声明如下:

private volatile Filter delegate;

可以看到,该属性也是一个Filter,然后看下DelegatingFilterProxy的拦截器doFilter实现:

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		// Lazily initialize the delegate if necessary.
		//如果代理的Filter还没加载,就按上面的流程加载一次,略。

		// Let the delegate perform the actual doFilter operation.
		//调用代理对象方法,完成拦截
		invokeDelegate(delegateToUse, request, response, filterChain);
	}
invokeDelegate实现如下:
	protected void invokeDelegate(
			Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		delegate.doFilter(request, response, filterChain);//调用代理对象的Filter完成拦截
	}

二、Filter的真实实现

第一步中我们看到了真正执行拦截的Bean其实是在Spring中配置的ShiroFilterFactoryBean(但是从名字可以看出来,它其实也不是最后执行拦截的,只是一个FactoryBean,用来生产我们需要的拦截器实例),ShiroFilterFactoryBean的相关结构如下:


可以看到,ShiroFilterFactoryBean继承了FactoryBean, BeanPostProcessor。这两个接口是Spring中用作拓展的接口,关于FactoryBean的实现:

FactoryBean接口的主要功能就是在getObject方法中返回一个对象,并把这个对象加入到Spring容器中,这样就可以被Spring容器中的其他Bean访问到,同时也可以访问其他的Bean

    public Object getObject() throws Exception {
        if (instance == null) {
            instance = createInstance();//创建Bean
        }
        return instance;
    }
	//返回值是一个Filter,作为我们需要的拦截器
	protected AbstractShiroFilter createInstance() throws Exception {

        log.debug("Creating Shiro Filter instance.");

        SecurityManager securityManager = getSecurityManager();//我们在Spring配置文件中配置的SecurityManager
        if (securityManager == null) {
            String msg = "SecurityManager property must be set.";
            throw new BeanInitializationException(msg);
        }

        if (!(securityManager instanceof WebSecurityManager)) {	//保证是Web环境下的SecurityManager
            String msg = "The security manager does not implement the WebSecurityManager interface.";
            throw new BeanInitializationException(msg);
        }

        FilterChainManager manager = createFilterChainManager();//创建对我们配置的拦截信息进行管理的管理器

        //Expose the constructed FilterChainManager by first wrapping it in a
        // FilterChainResolver implementation. The AbstractShiroFilter implementations
        // do not know about FilterChainManagers - only resolvers:
        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();//负责匹配Url后调用符合的Filter
        chainResolver.setFilterChainManager(manager);

        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
        //FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class
        //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
        //injection of the SecurityManager and FilterChainResolver:
        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);//负责执行拦截的Filter
    }
上面代码中有个很重要的属性就是
FilterChainManager

从名字可以明白,这个对象的作用就是管理拦截器链,下面是创建它的源码:

    protected FilterChainManager createFilterChainManager() {

        DefaultFilterChainManager manager = new DefaultFilterChainManager();//创建,并加入了Shiro默认的几个拦截器
        Map<String, Filter> defaultFilters = manager.getFilters();
        //添加一些属性
        for (Filter filter : defaultFilters.values()) {
            applyGlobalPropertiesIfNecessary(filter);
        }

        //对我们自己配置的Filter进行处理:添加到Filter列表中,并设置一些属性
        Map<String, Filter> filters = getFilters();
        if (!CollectionUtils.isEmpty(filters)) {
            for (Map.Entry<String, Filter> entry : filters.entrySet()) {
                String name = entry.getKey();
                Filter filter = entry.getValue();
                applyGlobalPropertiesIfNecessary(filter);
                if (filter instanceof Nameable) {
                    ((Nameable) filter).setName(name);
                }
                //'init' argument is false, since Spring-configured filters should be initialized
                //in Spring (i.e. 'init-method=blah') or implement InitializingBean:
                manager.addFilter(name, filter, false);
            }
        }

        //build up the chains:
        Map<String, String> chains = getFilterChainDefinitionMap();
        if (!CollectionUtils.isEmpty(chains)) {
            for (Map.Entry<String, String> entry : chains.entrySet()) {
                String url = entry.getKey();
                String chainDefinition = entry.getValue();
                manager.createChain(url, chainDefinition);
            }
        }

        return manager;
    }

创建FilterChainManager实例:

上面代码可以看到,Shiro在初始阶段就已经添加了一些Filter类:

    protected void addDefaultFilters(boolean init) {
        for (DefaultFilter defaultFilter : DefaultFilter.values()) {
            addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
        }
    }

DefaultFilter是一个枚举类型,它的定义如下:


如下图中,我们在Shiro配置的拦截器链等号后面对应的处理Filter就是这上面的:



对Filter需要的属性进行填充

	//如果需要,就为Filter添加我们配置文件中配置的successUrl、loginUrl、unauthorizedUrl(都是直接通过set设置)
    private void applyGlobalPropertiesIfNecessary(Filter filter) {
        applyLoginUrlIfNecessary(filter);
        applySuccessUrlIfNecessary(filter);
        applyUnauthorizedUrlIfNecessary(filter);
    }

对自定义的Filter进行处理:

        Map<String, Filter> filters = getFilters();		//获取我们在配置文件中配置的自定义Filter列表
        if (!CollectionUtils.isEmpty(filters)) {
            for (Map.Entry<String, Filter> entry : filters.entrySet()) {
                String name = entry.getKey();
                Filter filter = entry.getValue();
                applyGlobalPropertiesIfNecessary(filter);		//如上文中一样,如果需要就设置相关的全局属性
                if (filter instanceof Nameable) {
                    ((Nameable) filter).setName(name);
                }
                //'init' argument is false, since Spring-configured filters should be initialized
                //in Spring (i.e. 'init-method=blah') or implement InitializingBean:
                manager.addFilter(name, filter, false);		//添加到Filte列表中
            }
        }

自定义的Filter例子如下:

//一个继承自Shiro AdviceFilter的拦截器





创建SpringShiroFilter返回



SpringShiroFilter是一个内部类,定义如下:


SpringShiroFilter的父类AbstractShiroFilter已经基本上实现了需要的功能,而SpringShiroFilter的功能主要就体现在传入的两个参数上:

securityManager:提供realm(密码比对、角色权限获取等)、sessionManager、cacheManager等

PathMatchingFilterChainResolver:实现对Url的比对,并根据结果选择合适的拦截器等

//Filter的创建就已经讲完了,因为ShiroFilterFactoryBean实现FactoryBean的原因,DelegatingFilterProxy获取到的Bean就是上面返回的SpringShiroFilter,并调用他的doFilter方法(这个方法在父类中,通过子类的覆写,最后完成拦截功能的方法是doFilterInternal方法,后面会讲到)






教你 Shiro 整合 SpringBoot,避开各种坑 最近搞了下 Shiro 安全框架,找了一些网上的博客文章,但是一到自己实现的时候就遇到了各种坑,需要各种查资料看源码以及各种测试。 那么这篇文章就教大家如何将 Shiro 整合到 SpringBoot 中,并避开一些小坑,这次实现了基本的登陆以及角色权限,往后的文章也讲解了其他的功能,如 《教你 Shiro + SpringBoot 整合 JWT》 附上源码:https://... 阅读详情

相关推荐

手把手教你使用transciver-ip核的配置

手把手教你使用transciver-ip核的配置

u012938458的博客 5416

Shiro添加自己的Filter

因为前后端分离,添加了自己的过滤器,根据cookie判断传过来的uuid是否是登录的token 使用到了cache,稍后会加上源码也稍后上传 ShiroConfiguration @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { //这里设置了自己的过滤器 S

a295277302的博客 8399

告别信号毛刺!手把手教你用ADS和IBIS-AMI模型搞定PCIe Gen3眼图仿真

本文详细介绍了如何使用Keysight ADS和IBIS-AMI模型进行PCIe Gen3眼图仿真,解决高速信号传输中的信号质量问题。从仿真环境搭建、S参数预处理到眼图优化与故障排除,提供了一套完整的工程实践指南,帮助工程师提升PCIe Gen3接口的信号完整性。

weixin_28366053的博客 370

【若依(ruoyi)】 Shiro 向 ShiroFilterFactoryBean 中添加自定义过滤器

前言 若依(ruoyi): v4.3 shiro: 1.5.3 遇坑:shiro 自定义过滤器执行异常,无法排除已允许匿名访问的功能/URL 需求 使用 ruoyi 开发 restful 接口。因此,仅需要ruoyi开放如下功能: swagger-ui.html(为了更好的测试才开放,生产部署时去掉这个) /v2/api-docs(为了更好的测试才开放,生产部署时去掉这个) /api/** (所有的接口均以/api/开头) 除了上述需要开放的功能外,其余均不允许访问。 ruoyi 使用 shiro

sayyy的专栏 3568

MATPOWER下载安装教程

将MATPOWER文件复制在C:\Program Files (x86)\MATLAB\R2016b\bin目录下。原来的窗口中多了很多文件路径,点击【保存】,再点击【关闭】选择所要添加的MATPOWER文件夹,点击【选择文件夹】二、将MATPOWER放在bin目录下。找到菜单栏的【设置路径】点击【添加并包含子文件】一、从官网下载后解压。

weixin_47365903的博客 2万+

Android/AutoMotive 多用户文件操作与权限管理

本文深入探讨了Android/Automotive多用户系统的文件操作与权限管理机制。文章阐述了多用户隔离与共享的核心原理,重点介绍了如何使用adb指令精准管理不同用户的应用与数据,并提供了在Android Automotive车载场景下实现安全跨用户数据共享与权限控制的最佳实践。

weixin_29214691的博客 162

Spring 配置Shiro filter使用与自定义

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34367845的博客 273

Python邮件自动化实战:基于imaplib和email库的高效邮件管理方案

本文详细介绍了如何使用Python的imaplib和email库实现高效邮件自动化管理。通过实战案例展示自动收取、解析邮件、下载附件等核心功能,帮助开发者快速构建企业级邮件处理系统,大幅提升工作效率。特别适合需要处理大量邮件的金融、数据分析等场景。

weixin_30500105的博客 619

springboot下使用shiro自定义filter的个人经验

在springboot中使用shiro,由于没有了xml配置文件,因此使用的方法与spring中有些区别。在踩了无数个坑后,在此将springboot下使用shiro的步骤总结如下。由于本人对shiro的了解不是很深入,在实现了工作需求后就没有继续研究了,因此可能存在遗漏的地方或有错误的地方,还请多包涵。   目标: 在springboot中使用shiro 1.实现用户的登录验证 2.对...

BHSZZY的博客 9362

VMware ESXI 7.0实战:4T硬盘RAID1配置与性能调优全记录

本文详细记录了在VMware ESXI 7.0环境下,为Dell服务器配置两块4T硬盘组建RAID1并进行深度性能调优的全过程。文章重点解析了RAID控制器写入策略(Write-Back with BBU)、读取策略(Read-Ahead)的关键选择,并深入探讨了在ESXI虚拟机层面通过选用PVSCSI控制器、调整虚拟磁盘缓存策略(scsiX:Y.caching)等技巧,以最大化满足数据分析等IO密集型工作负载的需求,最终实现性能的显著提升。

gaochao的博客 259

谁还攥着旧的类加载器:Metaspace OOM 的元数据记账、类卸载条件与泄漏定位解析

MetaSpace区是JVM内存管理中的关键部分,负责存储类元数据。随着Java 8的推出,MetaSpace取代了PermGen区,但其灵活性也带来了新的挑战,尤其是在动态类加载和频繁类更新的场景下,容易导致MetaSpace内存溢出(OOM)问题。本文探讨了MetaSpace OOM的根本原因,包括类加载器泄漏、内存管理不当和GC效率低下等,并提供了一系列调优策略和解决方案,帮助开发者有效排查和防止此类问题的发生,确保应用程序的稳定性和高可用性。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 15万+

Springboot2集成Shiro框架(二)自定义Filter

1

New_Yao的博客 1010

word多级列表为什么会变成黑块解决思路

今天在写文档时,发现WORD5级的标题都变黑块了,找了度娘的资料,终于解决了。 第一种 1、光标bai放在黑快的右边,按向左的箭头,然后ctrl+shift+s,点击重新应用。 2、点击“定义新的多级列表”(不知道从哪儿找这个按钮的百度下),直接点确定。 3、这里很重要!!!不要直接保存,而是直接关掉word,会提示保存还是不保存,这个地方再点击保存。 第二种 Word2016 使用宏代码修复方法 1.找到视图-宏,打开 查看宏 2.创建宏 3.贴...

霍力强的专栏 8580

Shiro源码解析(持续更新中)

Shiro安全框架学习心得(源码分析) 概述 ​ shiro(http://shiro.apache.org/)是apache公司推出的一款轻量级开源安全框架。它支持身份验证,授权,加密和会话管理。Shiro提供易于理解的API,在项目整合时较为轻松。目前Shiro在国内的软件公司中使用较为广泛,是一个值得学习的框架。 一、基础概念 Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份; Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用

yuhelve3308的博客 2020

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

spring boot配置shiro自定义shiro filter匹配异常

原文地址:http://www.hillfly.com/2017/179.html最近忙着研究在 Springboot 上使用 Shiro 的问题。刚好就遇到个诡异事,百度 Google 也没找到啥有价值的信息,几番周折自己解决了,这里稍微记录下。自定义 FilterTOCShiro 支持自定义 Filter 大家都知道,也经常用,这里我也用到了一个自定义 Filter,主要用于验证接口调用的 A...

carllucasyu的博客 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

shiro——拦截器Filter

1. Filter接口(拦截器) shiro的拦截器是对Javax.servlet.Filter接口的扩展。本文的拦截器讲解是根据下图的继承顺序来讲的。 Filter源码如下:三部分,初始化、执行过滤、销毁。将var1 请求url放到FilterChain过滤链中去过滤。 public interface Filter { default void init(FilterCon...

dgh112233的博客 2662

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

shiro Filter加载和执行 源码解析

在使用若依框架(前后端不分离包含shiro安全框架)时,发现作者添加了验证码、登录帐号控制等自定义过滤器,于是对自定的过滤器加载和执行流程产生疑问。下面以验证码过滤器为例,对源码解析。

曾令胜的博客 1542

Shiro的Filter机制详解---源码分析

Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个)。 2, 为什么两个url规则都可以匹配同一个url,只执行第一个呢。 下面分别从这两个问题入手,最终阅读源码得到解答。 问题一解答 相同url但定义在不同的行,后面覆盖前...

246

Shiro权限控制(二):自定义Filter

通过自定义Filter实现权限配置,如某个URL需要某个角色的某个权限才能操作

kity9420的专栏 1万+

SpringBoot 整合Shiro 之 自定义Filter

结合上一篇 【Spring Boot 整合 Shiro】,第一次使用之后,但发现,Shiro过滤器对被 劫持 的API路径,若没“login.jsp”,则会直接返回 404 ,很不和谐。因此,捣鼓一下,自定义FIlter,通过自定义对其进行授权认证。 项目源码直通车 1. 自定义 Filter @Slf4j public class CustomFormAuthenticationFilter...

weixin_33709219的博客 1692

shiro学习23-shiro提供的filter-UserFilter类

这个类的javadoc的解释说:这个filter是的判断条件是当前用户必须登录或者是通过之前的登录时的remember me可以获得principalCollection,也就是必须知道用户是谁才可以。否则返回false,即不能通过这个filter。 源码如下:   protected boolean isAccessAllowed(ServletRequest request, Ser...

iteye_14612的博客 2522

shiro学习22-shiro提供的filter-AccessControlFilter

这个类的javadoc中说明了这个类才是限制应用中的资源能否被访问的filter,我们先看的onPreHandle方法: publicboolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { return isAccessA...

iteye_14612的博客 1955

Shiro 之 Filter(上):ShiroFilter

在上一篇中,我们分析了 Shiro Web 应用的入口 —— EnvironmentLoaderListener,它是一个 ServletContextListener,在 Web 容器启动的时候,它为我们创建了两个非常重要的对象: WebSecurityManager:它是用于 Web 环境的 SecurityManager 对象,通过读取 shiro.ini 中 [main] 片

wangshfa的专栏 2万+

shiro学习18-shiro提供的filter类-AdviceFilter

这个类和之前的AbstractShiroFilter是平级的,都是OnecPerRequestFilter的子类,我们从他的名字Advice中就能联想到他的用意——AOP,在spring中有很多的advice,也就是通知,比如前置通知,后置通知,最终通知等,这个类允许通过很多方法实现filter中的aop的特点,比如preHandle(前置通知),postHandle(后置通知,但是在抛异常的...

iteye_14612的博客 1749
上一篇: solrJ使用
下一篇: Shiro源码学习(二)应用拦截器链
finalcola
博客等级 码龄9年 37粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值