Shiro学习(19)动态URL权限限制

用过Spring Security的朋友应该比较熟悉对URL进行全局的权限控制,即访问URL时进行权限匹配;如果没有权限直接跳到相应的错误页面。Shiro也支持类似的机制,不过需要稍微改造下来满足实际需求。不过在Shiro中,更多的是通过AOP进行分散的权限控制,即方法级别的;而通过URL进行权限控制是一种集中的权限控制。本章将介绍如何在Shiro中完成动态URL权限控制。

本章代码基于《第十六章综合实例》,请先了解相关数据模型及基本流程后再学习本章。

表及数据SQL

请运行shiro-example-chapter19/sql/ shiro-schema.sql表结构

请运行shiro-example-chapter19/sql/ shiro-schema.sql数据

实体

具体请参考com.github.zhangkaitao.shiro.chapter19包下的实体。

Java代码

表示拦截的URL和角色/权限之间的关系,多个角色/权限之间通过逗号分隔,此处还可以扩展其他的关系,另外可以加如available属性表示是否开启该拦截。

DAO

具体请参考com.github.zhangkaitao.shiro.chapter19.dao包下的DAO接口及实现。

Service

具体请参考com.github.zhangkaitao.shiro.chapter19.service包下的Service接口及实现。

Java代码

基本的URL拦截的增删改查实现。

Java代码

UrlFilterServiceImpl在进行新增、修改、删除时会调用initFilterChain来重新初始化Shiro的URL拦截器链,即同步数据库中的URL拦截器定义到Shiro中。此处也要注意如果直接修改数据库是不会起作用的,因为只要调用这几个Service方法时才同步。另外当容器启动时会自动回调initFilterChain来完成容器启动后的URL拦截器的注册。

ShiroFilerChainManager

Java代码

1、init:Spring容器启动时会调用init方法把在spring配置文件中配置的默认拦截器保存下来,之后会自动与数据库中的配置进行合并。

2、initFilterChains:UrlFilterServiceImpl会在Spring容器启动或进行增删改UrlFilter时进行注册URL拦截器到Shiro。

拦截器及拦截器链知识请参考《第八章拦截器机制》,此处再介绍下Shiro拦截器的流程:

AbstractShiroFilter //如ShiroFilter/ SpringShiroFilter都继承该Filter

doFilter //Filter的doFilter

doFilterInternal //转调doFilterInternal

executeChain(request, response, chain) //执行拦截器链

FilterChain chain = getExecutionChain(request, response, origChain) //使用原始拦截器链获取新的拦截器链

chain.doFilter(request, response) //执行新组装的拦截器链

getExecutionChain(request, response, origChain) //获取拦截器链流程

FilterChainResolver resolver = getFilterChainResolver(); //获取相应的FilterChainResolver

FilterChain resolved = resolver.getChain(request, response, origChain); //通过FilterChainResolver根据当前请求解析到新的FilterChain拦截器链

默认情况下如使用ShiroFilterFactoryBean创建shiroFilter时,默认使用PathMatchingFilterChainResolver进行解析,而它默认是根据当前请求的URL获取相应的拦截器链,使用Ant模式进行URL匹配;默认使用DefaultFilterChainManager进行拦截器链的管理。

PathMatchingFilterChainResolver默认流程:

Java代码

默认实现有点小问题:

如果多个拦截器链都匹配了当前请求URL,那么只返回第一个找到的拦截器链;后续我们可以修改此处的代码,将多个匹配的拦截器链合并返回。

DefaultFilterChainManager内部使用Map来管理URL模式-拦截器链的关系;也就是说相同的URL模式只能定义一个拦截器链,不能重复定义;而且如果多个拦截器链都匹配时是无序的(因为使用map.keySet()获取拦截器链的名字,即URL模式)。

FilterChainManager接口:

Java代码

此接口主要三个功能:注册拦截器,注册拦截器链,对原始拦截器链生成代理之后的拦截器链,比如

Java代码

filters属性定义了拦截器;filterChainDefinitions定义了拦截器链;如/**就是拦截器链的名字;而user,sysUser就是拦截器名字列表。

之前说过默认的PathMatchingFilterChainResolver和DefaultFilterChainManager不能满足我们的需求,我们稍微扩展了一下:

CustomPathMatchingFilterChainResolver

Java代码

和默认的PathMatchingFilterChainResolver区别是,此处得到所有匹配的拦截器链,然后通过调用CustomDefaultFilterChainManager.proxy(originalChain, chainNames)进行合并后代理。

CustomDefaultFilterChainManager

Java代码

1、CustomDefaultFilterChainManager:调用其构造器时,会自动注册默认的拦截器;

2、loginUrl、successUrl、unauthorizedUrl:分别对应登录地址、登录成功后默认跳转地址、未授权跳转地址,用于给相应拦截器的;

3、filterChainDefinitionMap:用于存储如ShiroFilterFactoryBean在配置文件中配置的拦截器链定义,即可以认为是默认的静态拦截器链;会自动与数据库中加载的合并;

4、setDefaultFilterChainDefinitions:解析配置文件中传入的字符串拦截器链配置,解析为相应的拦截器链;

5、setCustomFilters:注册我们自定义的拦截器;如ShiroFilterFactoryBean的filters属性;

6、init:初始化方法,Spring容器启动时会调用,首先其会自动给相应的拦截器设置如loginUrl、successUrl、unauthorizedUrl;其次根据filterChainDefinitionMap构建默认的拦截器链;

7、initFilter:此处我们忽略实现initFilter,因为交给spring管理了,所以Filter的相关配置会在Spring配置中完成;

8、proxy:组合多个拦截器链为一个生成一个新的FilterChain代理。

Web层控制器

请参考com.github.zhangkaitao.shiro.chapter19.web.controller包,相对于第十六章添加了UrlFilterController用于UrlFilter的维护。另外,移除了控制器方法上的权限注解,而是使用动态URL拦截进行控制。

Spring配置——spring-config-shiro.xml

Java代码

filterChainManager是我们自定义的CustomDefaultFilterChainManager,注册相应的拦截器及默认的拦截器链。

Java代码

filterChainResolver是自定义的CustomPathMatchingFilterChainResolver,使用上边的filterChainManager进行拦截器链的管理。

Java代码

shiroFilter不再定义filters及filterChainDefinitions,而是交给了filterChainManager进行完成。

Java代码

最后把filterChainResolver注册给shiroFilter,其使用它进行动态URL权限控制。

其他配置和第十六章一样,请参考第十六章。

测试

1、首先执行shiro-data.sql初始化数据。

2、然后再URL管理中新增如下数据:

3、访问:8080/chapter19/user时要求用户拥有aa角色,此时是没有的所以会跳转到未授权页面;

4、添加aa角色然后授权给用户,此时就有权限访问:8080/chapter19/user。

实际项目可以在此基础上进行扩展。

版权声明:欢迎转载,希望在你转载的同时,,添加原文地址,谢谢配合

生活会变成什么样子?正因为时光流逝一去不复返,

Shiro学习(19)动态URL权限限制

相关文章:

你感兴趣的文章:

标签云: