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://... 阅读详情

相关推荐

Abaqus滞回问题求解—浆锚连接装配式剪力墙滞回模拟

当下土木工程研究生,多数都在从事装配式混凝土构件安全或装配式混凝土构件连接节点力学性能的研究。研究这类问题,几乎脱离不开对有限元软件的使用,Abaqus求解能力非常强大,但模型处理能力相对较弱。装配式混凝土结构的有限元计算与传统现浇结构相比,其节点处理起来相对复杂,计算结果往往需要凸显出连接节点力学特性,所以对建模精程度的要求较高。所以向大家介绍一款工具—HyperMesh软件(一下简称Hm),它是专业的有限元前处理工具,用于处理装配式混凝土构件或连接节点有限元模型比较合适。这篇文章主要介绍如何利用Hm处理

qq_31918049的博客 2902

Shiro添加自己的Filter

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

a295277302的博客 8399

SPMI、PMBus、AVSBus:三大电源管理总线对比与选型指南

在现代电子系统中,电源管理是确保高性能与低功耗平衡的核心技术。其原理在于通过数字通信协议,实现电源管理单元(PMIC)与用电芯片间的精准“对话”,从而动态调整供电。这项技术的核心价值在于提升系统能效、增强可靠性并简化设计。其应用场景广泛,从智能手机、服务器到汽车电子无处不在。具体实现上,衍生出了三大主流协议:为移动嵌入式高度集成的SPMI总线、专注于工业标准监控的PMBus总线,以及追求极致实时能效的AVSBus总线。理解SPMI在复杂时序控制与PMBus在标准化配置方面的异同,是进行电源架构选型与调试的关

ithome 451

【若依(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

避坑指南:你的VASP CI-NEB计算为什么不收敛?常见错误分析与解决思路

本文深入解析VASP CI-NEB计算不收敛的常见问题,提供从结构准备到参数设置的系统解决方案。针对过渡态计算中的能量曲线异常、中间图像偏离等典型问题,详细介绍了诊断方法和实用工具,帮助研究者高效解决CI-NEB收敛难题,提升计算效率。

weixin_29698641的博客 433

【为K8s的coredns配置上游DNS服务器】

为K8s的coredns配置上游DNS服务器一、背景描述二、如何修改coredns达到目的三、修改coredns 解析指定域名走指定dns①、get coredns configmap②、修改coredns configmap③、查询现有coredns pod并逐个重启④、验证解析是否正确 一、背景描述 有一个项目需要部署到客户内网,并通过nat映射实现外网访问! 项目中有多个服务之间调用是走的外网域名,项目采用k8s集群容器部署,客户的网络情况导致服务之间通过外网域名互调时总是 connection ti

那个那个 6671

Spring 配置Shiro filter使用与自定义

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

weixin_34367845的博客 273

3台虚拟机部署Doris详细文档(含校验步骤)

摘要:本文详细介绍了Apache Doris在3台虚拟机上的集群部署方案。采用1主FE+1从FE+1观察者FE+3BE的混合部署模式,确保元数据高可用性。硬件配置建议测试环境4核16GB内存,生产环境8核64GB内存。部署步骤包括系统环境配置(关闭防火墙、内核参数优化)、FE/BE节点配置启动、集群初始化验证等。重点配置了IP白名单(172.30.0.115)和数据目录(/data/doris)。通过MySQL客户端和WebUI可监控集群状态,实现千万级数据的实时分析能力,后续可通过增加BE节点线性扩展。

weixin_41026747的博客 933

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

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

BHSZZY的博客 9362

UVM实战 卷I学习笔记1——简单的UVM验证平台:只有driver

目录验证平台的组成最简单的验证平台——只有driverUVM如何搭建driver:加入factory机制加入objection机制加入virtual interface 个人《UVM实战卷I》学习随手笔记,此书作者:张强 验证平台的组成 一个验证平台要实现的基本功能: 模拟DUT的各种真实使用情况——给DUT施加各种激励→driver实现激励功能; 根据DUT的输出判断DUT行为是否与预期符合→scoreboard(也称为checker)——需注意判断的东西和判断的标准是什么; 收集DUT的输出并传递

weixin_41979380的博客 3891

蓝牙攻防实战指南:低功耗蓝牙

Bluetooth Low Energy(也称Bluetooth Smart)是经典蓝牙(Bluetooth Classic)的演进版本,设计目标是实现极低功耗,适用于无需频繁更换电池的设备,如智能手环、健康监测器、蓝牙标签等。Bluetooth Low Energy 是一项极具前景的无线通信技术,它以极低的功耗实现了短距离高效通信,广泛应用于智能设备和物联网领域。然而,其简化的协议结构和配对机制也带来了不小的安全挑战。

idlecloud0105的博客 683

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

1

New_Yao的博客 1010

基于NRF52833芯片的DW3000 SPI驱动接口代码实现

详细介绍基于NRF52833、nRF52820 、nRF52832 nRF52840 芯片的DW3000 硬件驱动接口代码

DT程序员的博客 1217

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

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

yuhelve3308的博客 2020

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

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

carllucasyu的博客 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

shiro——拦截器Filter

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

dgh112233的博客 2662

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

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、付费专栏及课程。

余额充值