Shiro 权限动态加载与配置精细讲解

shiro demo下载

Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载?

Shiro  是一个很完美的权限控制框架,一般我们会采用 shiro  的标签,在页面判断,从而来判断一些Button Link Tag  的显示与否,但是仅仅这样判断是不够的,如果用户知道链接,这就一点用都没有。所以我们后台还要有一层判断。这样才安全。今天来说说 Shiro  后台判断的这点事。

shiro标签讲解:

Freemarker  使用Shiro 标签的介绍:http://www.sojson.com/blog/143.html

JSP  使用Shiro 标签的介绍:http://www.sojson.com/blog/144.html

shiro一般是这样配置。

  1. <property name="filterChainDefinitions" >
  2. <value>
  3. /** = anon
  4. /page/login.jsp = anon
  5. /page/register/* = anon
  6. /page/index.jsp = authc
  7. /page/addItem* = authc,roles[数据管理员]
  8. /page/file* = authc,roleOR[普通用户,数据管理员]
  9. /page/listItems* = authc,roleOR[数据管理员,普通用户]
  10. /page/showItem* = authc,roleOR[数据管理员,普通用户]
  11. /page/updateItem*=authc,roles[数据管理员]
  12. </value>
  13. </property>

这样配置有什么问题?

shiro  加载配置,或者说校验配置,是从上而下的,也就是向上面的配置,其实是有问题的。可能不仔细看你没看出来,/** = anon  ,如果把这个配置在第一行,其实下面的配置都没用。因为是从上往下去匹配,只要匹配中了,就不匹配了,这个是重点,所以要有序

其次,我们知道,这样配置有一个问题,就是维护起来费劲,它不如单独的配置文件,比如我们常用properties 配置文件来配置一些经常修改的值。如:jdbc.properties 会配置一些数据库的链接,帐号、密码等。

说到这里,有的同学就会想,那么我们就用 properties 

properties 我们来看看有什么问题?

用 properties 配置,其实是没问题,问题就出在读取 properties 配置上。我们一般读取,或者说常用读取properties 配置文件,都是用相对应的 Java   JDK   自带提供java.util.Properties 工具类,我们可以看到这个工具类的情况。

  1. public class Properties extends Hashtable<Object,Object> {
  2. //Do some thing
  3. }

它继承了 Hashtable ,这就是出现了一个问题,Hashtable 是无序的。这就是关键点。

Shiro 权限拦截动态配置方案

1.重写java.util.Properties  工具类 ,继承 LinkedHashMap<K, V>()  ,LinkedHashMap()  是有序的。
</k, v>

2.自己写一个读取文件的工具类也可以解决。

我的实现是用ini配置文件,自己写了一个读取的工具类,已经封装好,欲知详情或者下载请点击:http://www.sojson.com/blog/139.html

里面有工具类的下载,本站的实现,以及本站发布的开源Demo项目:SpringMVC + Mybatis + Shiro + Redis 。

这个 Demo  里的配置文件:

  1. [base_auth]
  2. /u/**=anon
  3. /user/**=simple,login
  4. /js/**=anon
  5. /css/**=anon
  6. /open/**=anon
  7. #不用校验地址是否有权限
  8. /permission/selectPermissionById.shtml=simple,login
  9. /member/onlineDetails/**=simple,login
  10. /role/mypermission.shtml=simple,login
  11. /role/getPermissionTree.shtml=simple,login
  12. /role/selectRoleByUserId.shtml=simple,login
  13. #需要根据地址校验有无权限
  14. /permission/**=simple,login,permission
  15. /role/**=simple,login,permission
  16. /member/**=simple,login,permission
  17. /**=simple,login

配置文件加载类:

  1. package com.sojson.core.shiro.service.impl;
  2. import java.io.IOException;
  3. import java.util.Map;
  4. import java.util.Set;
  5. import javax.annotation.Resource;
  6. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  7. import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
  8. import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
  9. import org.apache.shiro.web.servlet.AbstractShiroFilter;
  10. import org.springframework.core.io.ClassPathResource;
  11. import com.sojson.common.utils.LoggerUtils;
  12. import com.sojson.core.config.INI4j;
  13. import com.sojson.core.shiro.service.ShiroManager;
  14. /**
  15. *
  16. * 开发公司:SOJSON在线工具 <p>
  17. * 版权所有:© www.sojson.com<p>
  18. * 博客地址:http://www.sojson.com/blog/ <p>
  19. * <p>
  20. *
  21. * 动态加载权限 Service
  22. *
  23. * <p>
  24. *
  25. * 区分 责任人 日期    说明<br/>
  26. * 创建 周柏成 2016年6月2日  <br/>
  27. *
  28. * @author zhou-baicheng
  29. * @email so@sojson.com
  30. * @version 1.0,2016年6月2日 <br/>
  31. *
  32. */
  33. public class ShiroManagerImpl implements ShiroManager {
  34. // 注意/r/n前不能有空格
  35. private static final String CRLF = "\r\n";
  36. @Resource
  37. private ShiroFilterFactoryBean shiroFilterFactoryBean;
  38. @Override
  39. public String loadFilterChainDefinitions() {
  40. StringBuffer sb = new StringBuffer();
  41. sb.append(getFixedAuthRule());//固定权限,采用读取配置文件
  42. return sb.toString();
  43. }
  44. /**
  45. * 从配额文件获取固定权限验证规则串
  46. */
  47. private String getFixedAuthRule(){
  48. String fileName = "shiro_base_auth.ini";
  49. ClassPathResource cp = new ClassPathResource(fileName);
  50. INI4j ini = null;
  51. try {
  52. ini = new INI4j(cp.getFile());
  53. } catch (IOException e) {
  54. LoggerUtils.fmtError(getClass(), e, "加载文件出错。file:[%s]", fileName);
  55. }
  56. String section = "base_auth";
  57. Set<String> keys = ini.get(section).keySet();
  58. StringBuffer sb = new StringBuffer();
  59. for (String key : keys) {
  60. String value = ini.get(section, key);
  61. sb.append(key).append(" = ")
  62. .append(value).append(CRLF);
  63. }
  64. return sb.toString();
  65. }
  66. // 此方法加同步锁
  67. @Override
  68. public synchronized void reCreateFilterChains() {
  69. // ShiroFilterFactoryBean shiroFilterFactoryBean = (ShiroFilterFactoryBean) SpringContextUtil.getBean("shiroFilterFactoryBean");
  70. AbstractShiroFilter shiroFilter = null;
  71. try {
  72. shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
  73. } catch (Exception e) {
  74. LoggerUtils.error(getClass(),"getShiroFilter from shiroFilterFactoryBean error!", e);
  75. throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
  76. }
  77. PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
  78. .getFilterChainResolver();
  79. DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
  80. .getFilterChainManager();
  81. // 清空老的权限控制
  82. manager.getFilterChains().clear();
  83. shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
  84. shiroFilterFactoryBean.setFilterChainDefinitions(loadFilterChainDefinitions());
  85. // 重新构建生成
  86. Map<String, String> chains = shiroFilterFactoryBean
  87. .getFilterChainDefinitionMap();
  88. for (Map.Entry<String, String> entry : chains.entrySet()) {
  89. String url = entry.getKey();
  90. String chainDefinition = entry.getValue().trim().replace(" ", "");
  91. manager.createChain(url, chainDefinition);
  92. }
  93. }
  94. public void setShiroFilterFactoryBean(
  95. ShiroFilterFactoryBean shiroFilterFactoryBean) {
  96. this.shiroFilterFactoryBean = shiroFilterFactoryBean;
  97. }
  98. }

具体请查看:

本站发布的开源Demo项目:SpringMVC + Mybatis + Shiro + Redis 。

Github下载:https://github.com/baichengzhou/SpringMVC-Mybatis-shiro

展开阅读全文

没有更多推荐了,返回首页