版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35608780/article/details/71630829
动态授权 在前端页面就可以对 资源路径和角色 进行配置 并且即时生效 以前在配置文件中写 现在写到了数据库中 方便了开发和维护
spring配置文件:
<!-- 引入数据源 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 注解扫描 -->
<context:component-scan base-package="cn.neusoft.dao,cn.neusoft.filter"></context:component-scan>
<!-- 配置数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
<!-- 自定义的shiro 过滤器 -->
<bean id="phoneFilter" class="cn.neusoft.filter.UserPhoneFilter">
<property name="userdao" ref="userDao"></property>
</bean>
<bean id="chainDefinitionSectionMetaSource" class="cn.neusoft.filter.ChainDefinitionSectionMetaSource">
<property name="filterChainDefinitions">
<value>
/userphone/login.action =anon
/user/login.action = anon
/login.jsp =anon
/user/all.action = authc
/userphone/select.action =authc
/userphone/* =phone
/url/all.action =authc
</value>
</property>
</bean>
<!-- Shiro的过滤器工厂BEAN : 间接地加载9个内置过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 安全管理器 :Shiro的核心组件,相当于大脑 -->
<property name="securityManager" ref="securityManager" />
<!-- 认证相关: 指定登陆页面,当用户未登陆时访问资源,则自动跳转到此页面 -->
<property name="loginUrl" value="/login.jsp" />
<!-- 授权相关:指定错误页面,当用户登陆后访问没有权限的资源时,自动跳转到此页面 -->
<property name="unauthorizedUrl" value="/error.html" />
<property name="filters">
<map>
<entry key="phone" value-ref="phoneFilter" />
</map>
</property>
<!-- shiro连接约束配置,在这里使用自定义的动态获取资源类 -->
<property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" />
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"></property>
</bean>
<!-- 自定义Realm -->
<bean id="userRealm" class="cn.neusoft.realm.UserRealm">
<property name="userService" ref="userService"></property>
<property name="user" ref="user"></property>
</bean>
</beans>
其中shirofilter 中的两个属性filters是自定义的shiro过滤器 filterChainDefinitionMap是shiro过滤器链 所以我们只要把数据库中的数据拿给filterChainDefinitionMap就好了 就完成从数据库中读取的事了
我们可以看到他引入了一些一个对象 这个对象中定义了一些基础的配置 这个类的主要目地就是把配置文件中配置的和数据库中的信息结合起来 然后把所有信息存入map返回
@Service
public class ChainDefinitionSectionMetaSource implements FactoryBean<Ini.Section>{
@Autowired
private UrlFilterDao urlFilterDao;
//配置文件中的信息会注入进来
public static String filterChainDefinitions;
@Autowired
private ShiroFilterFactoryBean shiroFilterFactoryBean;
/**
* 默认premission字符串
*/
public static final String PREMISSION_STRING="perms[\"{0}\"]";
//初始化权限
@Override
public Section getObject() throws Exception {
List<UrlFilter> list = urlFilterDao.selectall();
Ini ini = new Ini();
//加载默认的url
ini.load(filterChainDefinitions);
Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
//循环Resource的url,逐个添加到section中。section就是filterChainDefinitionMap,
//里面的键就是链接URL,值就是存在什么条件才能访问该链接
for (Iterator<UrlFilter> it = list.iterator(); it.hasNext();) {
UrlFilter resource = it.next();
//如果不为空值添加到section中
if(!StringUtils.isEmpty(resource.getUrl()) && !StringUtils.isEmpty(resource.getPerms())) {
section.put(resource.getUrl(), MessageFormat.format(PREMISSION_STRING,resource.getPerms()));
}
}
section.put("/*.html", "authc");
section.put("/*.action", "authc");
section.put("/*", "authc");
return section;
}
public void setFilterChainDefinitions(String filterChainDefinitions) {
this.filterChainDefinitions = filterChainDefinitions;
}
}
把配置文件与数据库中的信息结合 然后返回完成了从数据库中读取
第二大步 完成数据库的读取后 接下来是更新权限了 增删改路径权限后要立即生效 也就是重新构建shiro的过滤器链
主要是清空DefaultFilterChainManager里面的FilterChains,还有shiroFilterFactoryBean里面的FilterChainDefinitions;然后重新调用DefaultFilterChainManager的createChain方法,把资源重新设置进去即可
public void updatePermission(List<UrlFilter> list) {
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();
System.out.println(ChainDefinitionSectionMetaSource.filterChainDefinitions);
// 重新构建生成
//添加配置文件中的权限配置
shiroFilterFactoryBean.setFilterChainDefinitions(ChainDefinitionSectionMetaSource.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);
}
//添加数据库中的配置信息
for (UrlFilter u : list) {
manager.createChain(u.getUrl(), MessageFormat.format(PREMISSION_STRING,u.getPerms()));
}
manager.createChain("/*.html", "authc");
manager.createChain("/*.action", "authc");
manager.createChain("/*", "authc");
}
}
这个是更新方法 当权限路径被增删改时 把最新的数据传过来 清空原来的信息 把最新的信息设置进去 就OK了!
新手啊 还请多指教