Shiro第五篇【受权过滤、注解、JSP标签方式、与ehcache整合】

受权过滤器测试

咱们的受权过滤器使用的是permissionsAuthorizationFilter来进行拦截。咱们能够在application-shiro中配置filter规则java

<!--商品查询须要商品查询权限 -->
        /items/queryItems.action = perms[item:query]
        /items/editItems.action = perms[item:edit]

测试流程:
一、在applicationContext-shiro.xml中配置filter规则web

  • <!--商品查询须要商品查询权限 -->
  • /items/queryItems.action = perms[item:query]

二、用户在认证经过后,请求/items/queryItems.action
三、被PermissionsAuthorizationFilter拦截,发现须要“item:query”权限
四、PermissionsAuthorizationFilter**调用realm中的doGetAuthorizationInfo获取数据库中正确的权限**
五、PermissionsAuthorizationFilter对item:query 和从realm中获取权限进行对比,若是“item:query”在realm返回的权限列表中,受权经过。spring

realm中获取认证的信息,查询出该用户对应的权限,封装到simpleAuthorizationInfo中,PermissionsAuthorizationFilter会根据对应的权限来比对。数据库

@Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {

        //从 principals获取主身份信息
        //将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证经过填充到SimpleAuthenticationInfo中身份类型),
        ActiveUser activeUser =  (ActiveUser) principals.getPrimaryPrincipal();

        //根据身份信息获取权限信息
        //从数据库获取到权限数据
        List<SysPermission> permissionList = null;
        try {
            permissionList = sysService.findPermissionListByUserId(activeUser.getUserid());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //单独定一个集合对象 
        List<String> permissions = new ArrayList<String>();
        if(permissionList!=null){
            for(SysPermission sysPermission:permissionList){
                //将数据库中的权限标签 符放入集合
                permissions.add(sysPermission.getPercode());
            }
        }


    /*  List<String> permissions = new ArrayList<String>();
        permissions.add("user:create");//用户的建立
        permissions.add("item:query");//商品查询权限
        permissions.add("item:add");//商品添加权限
        permissions.add("item:edit");//商品修改权限
*/      //....

        //查到权限数据,返回受权信息(要包括 上边的permissions)
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //将上边查询到受权信息填充到simpleAuthorizationInfo对象中
        simpleAuthorizationInfo.addStringPermissions(permissions);

        return simpleAuthorizationInfo;
    }

在bean中咱们已经配置了:若是没有权限,那么跳转到哪一个JSP页面了apache

<!-- 经过unauthorizedUrl指定没有权限操做时跳转页面-->
        <property name="unauthorizedUrl" value="/refuse.jsp" />

到目前为止,如今问题又来了:编程

一、在applicationContext-shiro.xml中配置过虑器连接,须要将所有的url和权限对应起来进行配置,比较发麻不方便使用。缓存

二、每次受权都须要调用realm查询数据库,对于系统性能有很大影响,能够经过shiro缓存来解决。安全


使用注解式和标签式配置受权

上面的那种方法,仍是须要咱们将所有的url和权限对应起来进行配置,是比较不方便的。咱们可使用受权的另外两种方式markdown

  • 注解式
  • 标签式

注解式

若是要使用注解式,那么就必须在Spring中开启controller类aop支持session

<!-- 开启aop,对类代理 -->
    <aop:config proxy-target-class="true"></aop:config>
    <!-- 开启shiro注解支持 -->
    <bean  class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager" />
    </bean>

在Controller中使用注解来进行配置就好了,就不用在咱们的application-shiro中所有集中配置了

//商品信息方法
    @RequestMapping("/queryItems")
    @RequiresPermissions("item:query")//执行queryItems须要"item:query"权限
    public ModelAndView queryItems(HttpServletRequest request) throws Exception {

        System.out.println(request.getParameter("id"));

        //调用service查询商品列表
        List<ItemsCustom> itemsList = itemsService.findItemsList(null);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("itemsList", itemsList);
        // 指定逻辑视图名
        modelAndView.setViewName("itemsList");

        return modelAndView;
    }

jsp标签 受权

这里写图片描述

这里写图片描述

当调用controller的一个方法,因为该 方法加了@RequiresPermissions(“item:query”) ,shiro调用realm获取数据库中的权限信息,看”item:query”是否在权限数据中存在,若是不存在就拒绝访问,若是存在就受权经过。

当展现一个jsp页面时,页面中若是遇到,shiro调用realm获取数据库中的权限信息,看item:update是否在权限数据中存在,若是不存在就拒绝访问,若是存在就受权经过。


Shiro缓存

针对上边受权频繁查询数据库,须要使用shiro缓存

缓存流程

shiro中提供了对认证信息和受权信息的缓存。shiro默认是关闭认证信息缓存的,对于受权信息的缓存shiro默认开启的。主要研究受权信息缓存,由于受权的数据量大。

用户认证经过。

该用户第一次受权:调用realm查询数据库
该用户第二次受权:不调用realm查询数据库,直接从缓存中取出受权信息(权限标识符)。

使用ehcache和Shiro整合

导入jar包

这里写图片描述

配置缓存管理器,注入到安全管理器中

<!-- 缓存管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
    </bean>
 <!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm" /> <!-- 注入缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> </bean>

ehcache的配置文件shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!--diskStore:缓存数据持久化的目录 地址 -->
    <diskStore path="F:\develop\ehcache" />
    <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

缓存清空

若是用户正常退出,缓存自动清空。
若是用户非正常退出,缓存自动清空。

还有一种状况:

  • 当管理员修改了用户的权限,可是该用户尚未退出,在默认状况下,修改的权限没法当即生效。须要手动进行编程实现:在权限修改后调用realm的clearCache方法清除缓存。

清除缓存:

//清除缓存
    public void clearCached() {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }

sessionManager

和shiro整合后,使用shiro的session管理,shiro提供sessionDao操做 会话数据。

配置sessionManager

<!-- 会话管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!-- session的失效时长,单位毫秒 -->
        <property name="globalSessionTimeout" value="600000"/>
        <!-- 删除失效的session -->
        <property name="deleteInvalidSessions" value="true"/>
    </bean>

注入到安全管理器中

<!-- securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="customRealm" />
        <!-- 注入缓存管理器 -->
        <property name="cacheManager" ref="cacheManager"/>
        <!-- 注入session管理器 -->
        <property name="sessionManager" ref="sessionManager" />

</bean>
相关文章
相关标签/搜索