当前位置:首页 > Web开发 > 正文

第十九章 动态URL权限控制

2024-03-31 Web开发

目录贴: 跟我学Shiro目录贴

用过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代码  

public class UrlFilter implements Serializable {  

    private Long id;  

    private String name; //url名称/描述  

    private String url; //地址  

    private String roles; //所需要的角色,可省略  

    private String permissions; //所需要的权限,可省略  

}   

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

DAO

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

Service

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

Java代码  

public interface UrlFilterService {  

    public UrlFilter createUrlFilter(UrlFilter urlFilter);  

    public UrlFilter updateUrlFilter(UrlFilter urlFilter);  

    public void deleteUrlFilter(Long urlFilterId);  

    public UrlFilter findOne(Long urlFilterId);  

    public List<UrlFilter> findAll();  

}  

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

Java代码  

@Service  

public class UrlFilterServiceImpl implements UrlFilterService {  

    @Autowired  

private ShiroFilerChainManager shiroFilerChainManager;  

  

    @Override  

    public UrlFilter createUrlFilter(UrlFilter urlFilter) {  

        urlFilterDao.createUrlFilter(urlFilter);  

        initFilterChain();  

        return urlFilter;  

    }  

    //其他方法请参考源码  

    @PostConstruct  

    public void initFilterChain() {  

        shiroFilerChainManager.initFilterChains(findAll());  

    }  

}   

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

ShiroFilerChainManager 

Java代码  

@Service  

public class ShiroFilerChainManager {  

    @Autowired private DefaultFilterChainManager filterChainManager;  

    private Map<String, NamedFilterList> defaultFilterChains;  

    @PostConstruct  

    public void init() {  

        defaultFilterChains =   

          new HashMap<String, NamedFilterList>(filterChainManager.getFilterChains());  

    }  

    public void initFilterChains(List<UrlFilter> urlFilters) {  

        //1、首先删除以前老的filter chain并注册默认的  

        filterChainManager.getFilterChains().clear();  

        if(defaultFilterChains != null) {  

            filterChainManager.getFilterChains().putAll(defaultFilterChains);  

        }  

        //2、循环URL Filter 注册filter chain  

        for (UrlFilter urlFilter : urlFilters) {  

            String url = urlFilter.getUrl();  

            //注册roles filter  

            if (!StringUtils.isEmpty(urlFilter.getRoles())) {  

                filterChainManager.addToChain(url, "roles", urlFilter.getRoles());  

            }  

            //注册perms filter  

            if (!StringUtils.isEmpty(urlFilter.getPermissions())) {  

                filterChainManager.addToChain(url, "perms", urlFilter.getPermissions());  

            }  

        }  

    }  

}   

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拦截器链

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/42492.html