shiro不重启动态加载权限
最近一朋友让我帮他做一个后台权限管理的项目。我就在我原来的项目加加改改但是还是不理想,查了不少资料也走了不了弯路。。。。。。
shiro基本的配置我就不多说了这个很简单自己查查资料就完成…………下面是基本的配置不多说,如果这个静态的都不会配置那么就没必要继续往下看了,要稍微了解一点shiro的知识。另外要想动态加载权限的……思路就是重写ShiroFilterFactoryBean类中的setFilterChainDefinitions()方法
<bean id="myShiro" class="com.agnils.base.user.service.MyShiro">
<!-- <property name="userService" ref="userService"/> -->
</bean>
<!-- 配置权限管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- ref对应我们写的realm MyShiro -->
<property name="realm" ref="myShiro"/>
<!-- 使用下面配置的缓存管理器 -->
<property name="cacheManager" ref="cacheManager"/>
</bean> <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置我们的登录请求地址 -->
<property name="loginUrl" value="/login"/>
<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 -->
<property name="successUrl" value="/index"/>
<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
<property name="unauthorizedUrl" value="/403"/>
<!-- 权限配置 -->
<property name="filterChainDefinitions">
<value>
<!-- anon表示此地址不需要任何权限即可访问 -->
/static/**=anon
/uploadImg/**=anon
<!-- perms[user:query]表示访问此连接需要权限为user:query的用户 -->
/user=perms[user:query]
<!-- roles[manager]表示访问此连接需要用户的角色为manager -->
/user/add=roles[manager]
/user/del/**=roles[admin]
/user/edit/**=roles[manager]
/store/add=anon
/store/addStore=roles[manager]
/item/sale/**=roles[manager]
/login=anon
/customLogin=anon
/ordering/**=anon
/register=anon
/register/**=anon
<!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login-->
/wxConfig/**=roles[manager]
/wechat/**=anon
/exam/**=anon
/playVideos/**=anon
/**=authc
/graph/**=roles[admin]
/webPage/**=roles[admin]
/table/**=roles[admin]
</value>
</property>
</bean>
下面我开发说正题……
我先是想第一步从db中加载权限配置……
1.先改配置文件
<bean id="chainDefinitionSectionMetaSource"
class="com.agnils.base.role.service.ChainDefinitionSectionMetaSource">
<property name="filterChainDefinitions">
<value>
/sys/**=roles[admin]
/user/**=roles[manager]
/login=anon
/logout=anon
</value>
</property>
</bean>
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 配置我们的登录请求地址 -->
<property name="loginUrl" value="/login" />
<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 -->
<property name="successUrl" value="/index" />
<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
<property name="unauthorizedUrl" value="/403" />
<!-- 权限配置 -->
<property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource"></property>
</bean>
2添加java类
package com.agnils.base.role.service; import java.text.MessageFormat;
import java.util.List;
import java.util.Map; import org.apache.commons.lang.StringUtils;
import org.apache.shiro.config.Ini;
import org.apache.shiro.config.Ini.Section;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired; import com.agnils.base.role.dao.ResourceDao;
import com.agnils.base.role.entity.Resource; /**
* 标题、简要说明. <br>
* 类详细说明.
* <p>
* Copyright: Copyright (c) 2017-5-28 下午11:07:51
* <p>
*
* @author agnils@foxmail.com
* @version 1.0.0
*/
public class ChainDefinitionSectionMetaSource implements FactoryBean<Ini.Section> { @javax.annotation.Resource
private ResourceDao resourceDao;
@Autowired
ShiroFilterFactoryBean shiroFilterFactoryBean; private String filterChainDefinitions; public static final String PREMISSION_STRING = "roles[\"{0}\"]"; @Override
public Section getObject() throws Exception { List<Resource> list = (List) resourceDao.findAll();
Ini ini = new Ini();
ini.load(filterChainDefinitions);
Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
for (Resource resource : list) {
if (StringUtils.isNotBlank(resource.getValue()) && StringUtils.isNotBlank(resource.getPermission())) {
section.put(resource.getValue(), MessageFormat.format(PREMISSION_STRING, resource.getPermission()));
}
}
return section;
} @Override
public Class<?> getObjectType() {
return this.getClass();
} @Override
public boolean isSingleton() {
return false;
} public void setFilterChainDefinitions(String filterChainDefinitions) {
this.filterChainDefinitions = filterChainDefinitions;
} public void updatePermission() { synchronized (shiroFilterFactoryBean) { AbstractShiroFilter shiroFilter = null; try {
shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
} catch (Exception e) {
} // 获取过滤管理器
PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
.getFilterChainResolver();
DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager(); // 清空初始权限配置
manager.getFilterChains().clear();
shiroFilterFactoryBean.getFilterChainDefinitionMap().clear(); // 重新构建生成
shiroFilterFactoryBean.setFilterChainDefinitions(filterChainDefinitions);
Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap(); for (Map.Entry<String, String> entry : chains.entrySet()) {
String url = entry.getKey();
String chainDefinition = entry.getValue().trim().replace(" ", "");
manager.createChain(url, chainDefinition);
} }
} }
List<Resource> list = (List) resourceDao.findAll(); 这个就是从自己的权限表中取,动态添加,删除,修改的权限。在这个我就不累赘说了……
按照第一步的配置这样就可以从db中加载权限……但还是一个缺点就更改权限表中的数据时,还是重启才能生效……
第二步,这是本博文的重点 动态加载权限
要想实现动态加载就要重写ShiroFilterFactoryBean类代码如下:
package com.agnils.base.sys.permissionRole.service; import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.commons.lang.StringUtils;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.config.IniFilterChainResolverFactory; import com.agnils.base.role.dao.ResourceDao;
import com.agnils.base.role.entity.Resource;
import com.agnils.base.user.entity.Permission; /**
* 标题、简要说明. <br>
* 类详细说明.
* <p>
* Copyright: Copyright (c) 2017-6-3 下午9:51:02
* <p>
*
* @author agnils@foxmail.com
* @version 1.0.0
*/
public class ShiroPermissionFactory extends ShiroFilterFactoryBean { public static final String PREMISSION_STRING = "roles[\"{0}\"]"; // @javax.annotation.Resource
// private PermissionService permissionService; @javax.annotation.Resource
ResourceDao resourceDao; /** 记录配置中的过滤链 */
public static String filterChainDefinitions = "";//这个要和配置文件中的名称要一样 /**
* 初始化设置过滤链
*/
@Override
public void setFilterChainDefinitions(String definitions) {
filterChainDefinitions = definitions;// 记录配置的静态过滤链
Map<String, String> otherChains = new HashMap<String, String>();
List<Resource> list = (List) resourceDao.findAll();
for (Resource resource : list) {
if (StringUtils.isNotBlank(resource.getValue()) && StringUtils.isNotBlank(resource.getPermission())) {
otherChains.put(resource.getValue(), MessageFormat.format(PREMISSION_STRING, resource.getPermission()));
}
}
otherChains.put("/**", "authc");
// 加载配置默认的过滤链
Ini ini = new Ini();
ini.load(filterChainDefinitions);
Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
if (CollectionUtils.isEmpty(section)) {
section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
}
// 加上数据库中过滤链
section.putAll(otherChains);
setFilterChainDefinitionMap(section); }
}
Map<String, String> otherChains = new HashMap<String, String>();
List<Resource> list = (List) resourceDao.findAll();
for (Resource resource : list) {
if (StringUtils.isNotBlank(resource.getValue()) && StringUtils.isNotBlank(resource.getPermission())) {
otherChains.put(resource.getValue(), MessageFormat.format(PREMISSION_STRING, resource.getPermission()));
}
}
otherChains.put("/**", "authc");
这段代码就是从db中取自己配置的权限,每个人的都不一样,需要根据自己的情况修改
2.2 下面还要加一个FilterChainDefinitionsService类
package com.agnils.base.sys.permissionRole.service; import java.util.Map; import javax.annotation.Resource;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.stereotype.Service; /**
* 标题、简要说明. <br>
* 类详细说明.
* <p>
* Copyright: Copyright (c) 2017-6-3 下午9:49:01
* <p>
*
* @author agnils@foxmail.com
* @version 1.0.0
*/
@Service
public class FilterChainDefinitionsService { @Resource
private ShiroPermissionFactory permissionFactory; public void reloadFilterChains() {
synchronized (permissionFactory) { //强制同步,控制线程安全
AbstractShiroFilter shiroFilter = null; try {
shiroFilter = (AbstractShiroFilter) permissionFactory.getObject(); PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver) shiroFilter
.getFilterChainResolver();
// 过滤管理器
DefaultFilterChainManager manager = (DefaultFilterChainManager) resolver.getFilterChainManager();
// 清除权限配置
manager.getFilterChains().clear();
permissionFactory.getFilterChainDefinitionMap().clear();
// 重新设置权限
permissionFactory.setFilterChainDefinitions(ShiroPermissionFactory.filterChainDefinitions);//传入配置中的filterchains Map<String, String> chains = permissionFactory.getFilterChainDefinitionMap();
//重新生成过滤链
if (!CollectionUtils.isEmpty(chains)) {
for (Map.Entry<String, String> chain : chains.entrySet()) {
manager.createChain(chain.getKey(), chain.getValue().replace(" ", ""));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}}
好代码的都已完成,如果你做到这一步那你调reloadFilterChains()方法 。 在ShiroFilterFactoryBean类的section.putAll(otherChains);方法会报空指针异常……这个问题阻挠我好长时间。最后查了一下资料。问题出现在配置文件中,
2.3 更改配置文件
<bean id="myShiro" class="com.agnils.base.user.service.MyShiro">
<!-- <property name="userService" ref="userService"/> -->
</bean>
<!-- 配置权限管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- ref对应我们写的realm MyShiro -->
<property name="realm" ref="myShiro" />
<!-- 使用下面配置的缓存管理器 -->
<property name="cacheManager" ref="cacheManager" />
</bean>
<!-- <bean id="chainDefinitionSectionMetaSource"
class="com.agnils.base.role.service.ChainDefinitionSectionMetaSource">
<property name="filterChainDefinitions">
<value>
/sys/**=roles[admin]
/user/**=roles[manager]
/login=anon
/logout=anon
</value>
</property>
</bean> -->
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<!-- <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> -->
<bean id="shiroFilter" class="com.agnils.base.sys.permissionRole.service.ShiroPermissionFactory">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 配置我们的登录请求地址 -->
<property name="loginUrl" value="/login" />
<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 -->
<property name="successUrl" value="/index" />
<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
<property name="unauthorizedUrl" value="/403" />
<!-- 权限配置 -->
<!-- <property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource"></property> -->
<property name="filterChainDefinitions">
<value>
/sys/**=roles[admin]
/user/**=roles[manager]
/login=anon
/logout=anon
</value>
</property>
</bean>
写了控制类 ReloadController
package com.agnils.base.sys.permissionRole.web; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import com.agnils.base.sys.permissionRole.service.FilterChainDefinitionsService; /**
* 标题、简要说明. <br>
* 类详细说明.
* <p>
* Copyright: Copyright (c) 2017-6-3 下午10:44:27
* <p>
* @author agnils@foxmail.com
* @version 1.0.0
*/
@Controller
public class ReloadController { @Autowired
FilterChainDefinitionsService filterChainDefinitionsService; @RequestMapping(value="/reloadRole")
public void reloadRole(HttpServletRequest request){
filterChainDefinitionsService.reloadFilterChains();
}
}
删除,添加 db中的表权限自己测试通过,符合自己要求……
这个里我想说一句,本篇没有全部的配置文件,但主要的关于shiro都在里面,本文了不给伸手党写的……因为每个人的表,不一样所以要改的地方……
如遇到问题可以留言或都email联系……
shiro不重启动态加载权限的更多相关文章
- SpringBoot集成Shiro 实现动态加载权限
一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...
- 基于xml 实现动态加载权限功能树列表---EFSFrame企业级开发架构
在学习EFSFrame框架的过程中,感触最深的就是通过xml来实现前台与后台数据的交互,页面设计灵活,不用管后台如何写的,前台与后台的交互唯一的交互通道都是xml,在我们需要添加页面.添加规定的格式的 ...
- 6.0动态加载权限用PermissionGen
ndroid 6.0 新增加了运行时的动态添加权限,在此介绍一个第三方库,PermissionGen,可以很方便简洁的增加 6.0权限 首先给大家上 PermissionGen 库地址:https: ...
- Asp.Net Core 项目实战之权限管理系统(8) 功能菜单的动态加载
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- 利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载
简述 可能大家都知道,php中有一个函数叫debug_backtrace,它可以回溯跟踪函数的调用信息,可以说是一个调试利器. 好,来复习一下 01 one(); 02 03 function one ...
- (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】
原文地址:http://www.cnblogs.com/melonblog/archive/2013/05/09/3062303.html 原文作者:豆浆油条 - melon 本文示例代码测试环境是W ...
- SpringSecurity动态加载用户角色权限实现登录及鉴权
很多人觉得Spring Security实现登录验证很难,我最开始学习的时候也这样觉得.因为我好久都没看懂我该怎么样将自己写的用于接收用户名密码的Controller与Spring Security结 ...
- Spring与Shiro整合 加载权限表达式
Spring与Shiro整合 加载权限表达式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 如何加载权限表达式 我们在上章内容中画了一张图,里面有三个分项,用户 角色 权限: 那 ...
- vue-element-admin实战 | 第二篇: 最小改动接入后台实现根据权限动态加载菜单
一. 前言 本篇基于 有来商城 youlai-mall微服务项目,通过对vue-element-admin的权限菜单模块理解个性定制其后台接口,实现对vue-element-admin工程几乎不做改动 ...
随机推荐
- vb中创建xml
这里是原生的做法,具体使用可做相应的封装: Private Function GetUpdateRoomXml() As String Dim xmlDOM As New Xm ...
- php流程管理
流程控制即某个人发起一个流程,通过一层一层审核,通过后,完成整个流程,若有一层审核未通过,中断整个流程.即结束! 比如请假流程: 某一员工发起一个请假流程,那么这个流程的节点人员即他的上级,上上级,上 ...
- 获取camera截屏图片
Camera camera; SpriteRenderer sprRender; Texture2D t2d = New Texture2D(1300, 760, TextureFormat.RGB2 ...
- 深度学习入门实战(二)-用TensorFlow训练线性回归
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者 :董超 上一篇文章我们介绍了 MxNet 的安装,但 MxNet 有个缺点,那就是文档不太全,用起来可能 ...
- MySQL之改_update
MySQL增删改查之改_update UPDATE语句 进行数据记录的更新. 1.更新单个表中的值 语法: UPDATE [IGNORE] table_reference SET col_name1= ...
- 使用webpack打包css和js
1.安装webpack. npm install webpack -g 2.创建一个文件夹app. 3.新建文件test.js. require("!style-loader!css-loa ...
- Angular2.js——多个组件
目前我们的英雄列表和英雄详情位于同一个文件的同一个组件中,我们将来可能会受到新的需求,修改这个组件又不能影响另外一个.然而每一次更改都会给这两个组件带来风险和双倍的测试负担,没有任何好处.如果我们需要 ...
- 利用Python进行简单的图像识别(验证码)
这是一个最简单的图像识别,将图片加载后直接利用Python的一个识别引擎进行识别 将图片中的数字通过 pytesseract.image_to_string(image)识别后将结果存入到本地的txt ...
- linux上安装tcl
1. 首先下载安装包,推荐下载activetcl(对tcl源码进行了预编译,安装步骤简单).打开网址http://activestate.com找到activetcl的社区版(社区版是免费的,找到li ...
- hdu2059 龟兔赛跑 DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2059 虽然 知道是DP ,刚开始一直没有想出状态转移方程. 刚开始的思路就是定义dp[i]表示到达第i ...