打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
在项目中集成shiro权限框架(3)

Shirospring已经有完整的整合方法,所以,我们先在web.xml中添对过滤器,将需要验证的请求,拦截到shiro中。

<!—shiro过滤器-->

    <filter>

       <filter-name>shiroFilter</filter-name>

       <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

       <init-param>

           <param-name>targetFilterLifecycle</param-name>

           <param-value>true</param-value>

       </init-param>

    </filter>

 

    <filter-mapping>

       <filter-name>shiroFilter</filter-name>

       <url-pattern>/*</url-pattern>

 </filter-mapping>

 

spring配置中添加下面的支持bean.

<!-- 权限or判定器-->

    <beanid="roleOrFilter"class="com.my.commons.RolesOrFilter">

    </bean>

    

    <!-- 认证数据库存储-->

    <beanid="myRealm"class="com.my.service.impl.DbAuthRealm">

    </bean>

 

    <!-- 权限管理器-->

    <beanid="securityManager"class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

       <propertyname="realms">

           <list>

              <refbean="myRealm"/>

           </list>

       </property>

    </bean>

 

    <beanid="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"depends-on="roleOrFilter">

    

       <propertyname="securityManager"ref="securityManager"/>

 

       <propertyname="loginUrl"value="/login.jsp"/>

       <propertyname="successUrl"value="/main"/>

       <propertyname="unauthorizedUrl"value="/commons/unauth.jsp"/>

       

       <!-- 读取自定义权限内容-->

       <propertyname="filterChainDefinitions"value="#{authService.loadFilterChainDefinitions()}"/>   

       <propertyname="filters">

           <map>

              <entrykey="roleOrFilter"value-ref="roleOrFilter">

              </entry>

           </map>

       </property>

    </bean>

 

    <beanid="lifecycleBeanPostProcessor"class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

 

 

 

其中filterChainDefinitions部分,简单的项目可以直接写死,我们这里采用的是启动时读取生成,如果写死,将会出现类似下面的代码:

<property name="filterChainDefinitions">

           <value>

              /js/** = anon

              /css/** = anon

              /login.jsp = anon

              /login = anon

              /docs/doc1.jspauthc,roleOrFilter[admin,dev]

              /admin/manager.jsp = authc, roleOrFilter[admin]

              /admin/user/* = authc, rest[/admin/user/*]

              /userinfo/myinfo.jsp = authc,roleOrFilter[test,dev,admin]

              /** = authc

           </value>

       </property>

 

这段静态权限代码中用到了过滤器,我得给大家说一下:

anon部分是不需要进行验证的,即这部分是要放行的(注意***是有区别的,**表示该目录下的所有,当然也包括子目录下的东西,而*仅指当前目录下的东西)。

Authc,这个是需要登录的人才可以访问的。

roleOrFile,这个是我定义的,只要这个过滤器中的一个角色满足,即可访问,而shiro提供的role过滤器,是当所有角色都满足时才可访问。

Restrestful过滤器,会将get,post,put,delete转换为对资源的read.create,modify,delete操作。

当然,shiro还提供了其它的过滤器,大家可以自己去看看,比如:permission过滤器,shiro对权限的描述采用wildcard字串,功能强大且可读性强。

另外一点要接出,shiro在里使用最先匹配规则,一旦匹配成功,将不再进行后续的过滤规则检查,因此,在书写时一定要注意顺序,比如,你把/** = anon写到第一行,那么后面的一切都将不会再检测。

好了,下面来讲如何动态生成这个规则,大家看我的配置中有value="#{authService.loadFilterChainDefinitions()}",这个是spring el表达式语言,表示调用容器中的另一个bean的方法,把这个方法的返回结果,赋值给filterChainDefinitions属性。

在些再补充一些权限字串的知识:

shiro所支持的广义权限字串表达式,共有三种:

1、简单方式

比如:subject.isPermitted("editNews"),表示判断某操作者是否有【编辑新闻】的权限。

2、细粒度方式

比如:subject.isPermitted("News:create"),表示判断某操作者是否有【新建新闻】的权限。

3、实例级访问方式

比如:subject.isPermitted("News:edit:10"),表示判断某操作者是否有【编辑id号是10新闻】的权限。

上面3种方式中,可以用*表示所有,例如:"News:*"为对所有新闻的操作,"*:create"对所有事务都可以新增。还可以用 逗号 表示或都,"News:edit:10,11"表示可对10,11号新闻进行编辑。

如果要写页面权限,可参照如下配置:

/index.jsp = anon
/admin/** = authc, roles[admin]
 /docs/** = authc, perms[document:read]
 /** = authc

 

我定义了一个权限相关的接口,如下:

/**

 权限管理相关方法

 @authorljh

 *

 */

public interfaceIAuthService{

    /**

     加载过滤配置信息

     @return

     */

    publicString loadFilterChainDefinitions();

    

    /**

     重新构建权限过滤器

     一般在修改了用户角色、用户等信息时,需要再次调用该方法

     */

    public voidreCreateFilterChains();

 

}

 

 

其中一个方法用于加载生成权限规则字串,另一个,用于用户在系统中更改了角色-菜单,角色-功能关系时,动态重新生效的方法,实现类如下:

@Service(value="authService")

public classAuthServiceImplimplementsIAuthService {

    

    private static finalLogger log= Logger.getLogger(AuthServiceImpl.class);

    

    //注意/r/n前不能有空格

    private static finalString CRLF"\r\n";

    private static finalString LAST_AUTH_STR"/** =authc\r\n";

    

    @Resource

    privateShiroFilterFactoryBean shiroFilterFactoryBean;

    

    @Resource

    privateIBaseDao dao;

 

    @Override

    publicString loadFilterChainDefinitions() {

 

       

       StringBuffer sb = newStringBuffer("");

       sb.append(getFixedAuthRule())

       .append(getDynaAuthRule())

       .append(getRestfulOperationAuthRule())

       .append(LAST_AUTH_STR);

 

       

       returnsb.toString();

    }

    

    //生成restful风格功能权限规则

    privateString getRestfulOperationAuthRule() {

       

       List<Operation> operations = dao.queryEntitys("from Operation o"newObject[]{});

       

       Set<String> restfulUrls = newHashSet<String>();

       for(Operation op : operations) {

           restfulUrls.add(op.getUrl());

       }

       StringBuffer sb  newStringBuffer("");

       for(Iterator<String> urls =  restfulUrls.iterator(); urls.hasNext(); ) {

           String url = urls.next();

           if(! url.startsWith("/")) {

              url = "/"+ url ;

           }

           sb.append(url).append("=").append("authc, rest[").append(url).append("]").append(CRLF);

       }

       returnsb.toString();

       

       

    }

    

    

    //根据角色,得到动态权限规则

    privateString getDynaAuthRule() {

       

       StringBuffer sb = newStringBuffer("");

       Map<String, Set<String>> rules = newHashMap<String,Set<String>>();

       

       List<Role> roles = dao.queryEntitys("from Role r left join fetch r.menus"newObject[]{});

       for(Role role: roles) {

           for(Iterator<Menu> menus =role.getMenus().iterator(); menus.hasNext();) {

              String url = menus.next().getUrl();

              if(!url.startsWith("/")) {

                  url = "/"+ url;

              }

              if(!rules.containsKey(url)) {

                  rules.put(url, newHashSet<String>());

              }

              rules.get(url).add((role.getRoleCode()));

           }

       }

       

       for(Map.Entry<String, Set<String>> entry :rules.entrySet()) {

           sb.append(entry.getKey()).append(" = ").append("authc,roleOrFilter").append(entry.getValue()).append(CRLF);

       }

       

       returnsb.toString();

    }

    

    

    //得到固定权限验证规则串

    privateString getFixedAuthRule() {

       

       StringBuffer sb = newStringBuffer("");

       

       ClassPathResource cp = newClassPathResource("fixed_auth_res.properties");

       Properties properties = newOrderedProperties();

       try{

           properties.load(cp.getInputStream());

       catch(IOException e) {

           log.error("loadfixed_auth_res.properties error!", e);

           throw newRuntimeException("load fixed_auth_res.properties error!");

       }

       for(Iteratorits = properties.keySet().iterator();its.hasNext();) {

           String key = (String)its.next();

           sb.append(key).append(" = ").append(properties.getProperty(key).trim()).append(CRLF);

           

       }      

       returnsb.toString();

       

    }

    

    @Override

    //此方法加同步锁

    public synchronized voidreCreateFilterChains() {

       

       AbstractShiroFilter shiroFilter = null;

       try{

           shiroFilter = (AbstractShiroFilter)shiroFilterFactoryBean.getObject();

       catch(Exception e) {

           log.error("getShiroFilter from shiroFilterFactoryBean error!", e);

           throw newRuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");

       }

       

       PathMatchingFilterChainResolver filterChainResolver =(PathMatchingFilterChainResolver)shiroFilter.getFilterChainResolver();

       DefaultFilterChainManager manager =(DefaultFilterChainManager)filterChainResolver.getFilterChainManager();

 

       //清空老的权限控制

       manager.getFilterChains().clear();

       

 

       shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();

       shiroFilterFactoryBean.setFilterChainDefinitions(loadFilterChainDefinitions());

       //重新构建生成

       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);

        }

       

    }

 

}


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
我的shiro之旅: 八 shiro session 共享的进一步
JAVA版微信支付V3-完全版
jfinal-shiro的shiro注解结合数据库url路径过滤,动态维护你的权限系统,支持ajax
springrain技术详解(3)
shiro用authc配置url和用注解@RequiresAuthentication的问题
在 Web 项目中应用 Apache Shiro
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服