Shiro第五篇【受權過濾、註解、JSP標籤方式、與ehcache整合】

受權過濾器測試

咱們的受權過濾器使用的是permissionsAuthorizationFilter來進行攔截。咱們能夠在application-shiro中配置filter規則css

<!--商品查詢須要商品查詢權限 -->
        /items/queryItems.action = perms[item:query]
        /items/editItems.action = perms[item:edit]

測試流程:
一、在applicationContext-shiro.xml中配置filter規則java

  • <!--商品查詢須要商品查詢權限 -->
  • /items/queryItems.action = perms[item:query]

二、用戶在認證經過後,請求/items/queryItems.action
三、被PermissionsAuthorizationFilter攔截,發現須要「item:query」權限
四、PermissionsAuthorizationFilter**調用realm中的doGetAuthorizationInfo獲取數據庫中正確的權限**
五、PermissionsAuthorizationFilter對item:query 和從realm中獲取權限進行對比,若是「item:query」在realm返回的權限列表中,受權經過。web

realm中獲取認證的信息,查詢出該用戶對應的權限,封裝到simpleAuthorizationInfo中,PermissionsAuthorizationFilter會根據對應的權限來比對。spring

@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頁面了數據庫

<!-- 經過unauthorizedUrl指定沒有權限操做時跳轉頁面-->
        <property name="unauthorizedUrl" value="/refuse.jsp" />

到目前爲止,如今問題又來了:apache

一、在applicationContext-shiro.xml中配置過慮器連接,須要將所有的url和權限對應起來進行配置,比較發麻不方便使用。編程

二、每次受權都須要調用realm查詢數據庫,對於系統性能有很大影響,能夠經過shiro緩存來解決。緩存


使用註解式和標籤式配置受權

上面的那種方法,仍是須要咱們將所有的url和權限對應起來進行配置,是比較不方便的。咱們能夠使用受權的另外兩種方式安全

  • 註解式
  • 標籤式

註解式

若是要使用註解式,那麼就必須在Spring中開啓controller類aop支持markdown

<!-- 開啓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>
相關文章
相關標籤/搜索