前言
- 若依(ruoyi): v4.3
- shiro: 1.5.3
- 遇坑:shiro 自定义过滤器执行异常,无法排除已允许匿名访问的功能/URL
需求
使用 ruoyi 开发 restful 接口。因此,仅需要ruoyi开放如下功能:
- swagger-ui.html(为了更好的测试才开放,生产部署时去掉这个)
- /v2/api-docs(为了更好的测试才开放,生产部署时去掉这个)
- /api/** (所有的接口均以
/api/
开头)
除了上述需要开放的功能外,其余均不允许访问。
ruoyi 使用 shiro 进行权限控制。因此需要通过配置 shiro 来达到目的。
操作
实现思路
- 将所需开放的功能配置为允许匿名访问
- 将不需要开放的功能均拒绝访问
编写拒绝访问的 shiro 过滤器
public class DenyAllFilter extends PathMatchingFilter {
@Override
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
HttpServletRequest hsr = (HttpServletRequest) request;
System.out.println("DenyAllFilter, request is not allow : " + hsr.getRequestURI());
return false;
}
}
修改 ShiroConfig
/**
* Shiro过滤器配置
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// Shiro的核心安全接口,这个属性是必须的
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 自定义过滤器
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
filters.put("denyAllFilter", denyAllFilter());
shiroFilterFactoryBean.setFilters(filters);
// 定义过滤器链
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/api/**", "anon");
filterChainDefinitionMap.put("/v2/api-docs**", "anon");
filterChainDefinitionMap.put("/swagger**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/favicon.ico**", "anon");
filterChainDefinitionMap.put("/**", "denyAllFilter");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public DenyAllFilter denyAllFilter()
{
DenyAllFilter denyAllFilter = new DenyAllFilter();
return denyAllFilter;
}
嗯…,这就好了。
出了有坑之外,一切都很完美。
有坑
有坑不怕,填上就行。
启动ruoyi,访问地址http://localhost:8085/aswagger-ui.html
,得到了个很白的页面。这是遇到坑了。这个坑不分析了,有兴趣的可以参考这里。
说一下结论:
- 这里遇到的坑是:不该将 filter 交给 spring 创建。
简单解释一下:
- shiro 的权限控制是通过 filter 控制的,且 shiro 自己维护了一个 filter chain。
- spring 也维护了一个 filter chain。
denyAllFilter
交给 spring 创建后,denyAllFilter
虽然如愿的加入到了 shiro filter chain 中,但,同时也加入到了 spring filter chain 中。
解决办法:
denyAllFilter
不交给 spring 创建即可。将 denyAllFilter
方法前面的 @Bean 注解去掉即可。
public DenyAllFilter denyAllFilter()
{
DenyAllFilter denyAllFilter = new DenyAllFilter();
return denyAllFilter;
}
参考
https://www.cnblogs.com/guitu18/p/12163872.html