简介
- 即访问url时进行权限匹配,如果没有权限则直接跳到错误页面。
- 在Shiro中,更多的是通过AOP进行方法级别的权限控制,而通过url进行权限控制是一种集中的权限控制。
示例
- 拦截器:如authc、anon等字符串为一个拦截器;拦截器链:url=authc为一条拦截器链;拦截器链集合:url1=authc,url2=anon为拦截器链集合。
- 仿chapter16的示例,主要功能是用户、公司、角色和资源之间关系的调整,如修改用户所属公司、所有角色,资源所需权限、角色所有资源等。
- 数据库:除user、organization、role、resource外,新增一张url-filter表,映射url和角色、权限之间的关系(多个角色、权限之间用逗号分隔),即动态的拦截器链。
- 实体:多一个URLFilter类,封装url和权限、角色间的关系。
public class UrlFilter implements Serializable {
private Long id;
private String name; //url名称或描述
private String url; //地址
private String roles; //所需角色,可省略,用逗号分隔
private String permissions; //所需权限,可省略,用逗号分隔
//setter/getter
}
- dao、service、controller层都增加对UrlFilter的增删查改。
- controller层撤销shiro的权限注解,因为要用数据库中动态的拦截器链来实现。
- 因为数据库中的拦截器链都是要合并到shiro中的,所以在service层中,更新数据库拦截器链后,要重置shiro中的拦截器链集合,以同步此更新,否则更新不生效。比如:
@Override
public void deleteUrlFilter(Long urlFilterId) {
urlFilterDao.deleteUrlFilter(urlFilterId);
initFilterChain();
}
/**
* @Author haien
* @Description 初始化Shiro的url拦截器,用于在url表改动后,
将数据库发送的改动同步到Shiro中。
* @Date 2019/4/5
* @Param []
* @return void
**/
@PostConstruct //当DI容器实例化当前bean时,该方法会自动执行
public void initFilterChain() {
//将配置文件和数据库的拦截器链合并
shiroFilerChainManager.initFilterChains(findAll()); //先清空集合再去加载
}
- ShiroFilterChainManager: 调用了FilterChainManager的方法,先清空拦截器链集合再重新加载。
@Service
public class ShiroFilterChainManager {
//过滤链管理器,管理所有过滤器,包含增删查改等操作
@Resource
private DefaultFilterChainManager filterChainManager; //注入的是
//CustomDefaultFilterChainManager
//默认过滤链,包含在配置文件中提到的所有过滤器
private Map<String,NamedFilterList> defaultFilterChains;
/**
* @Author haien
* @Description 获取配置文件中all过滤器,之后会自动与数据库中包含的过滤器合并
* @Date 2019/4/5
* @Param []
* @return void
**/
@PostConstruct //DI容器实例化该bean时自动执行该方法
public void inti(){
//获取配置文件中all拦截器(静态的,不会变)
defaultFilterChains=new HashMap<>(filterChainManager.getFilterChains());
}
/**
* @Author haien
* @Description 初始化过滤链,默认+数据库
* @Date 2019/4/5
* @Param [urlFilters]
* @return void
**/
public void initFilterChains(List<UrlFilter> urlFilters){
//1. 删除以前老的filter chain并注册默认的
filterChainManager.getFilterChains().clear();
if(defaultFilterChains!=null)
filterChainManager.getFilterChains().putAll(defaultFilterChains);
//2. 注册数据库中的