简介

  • 即访问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. 注册数据库中的