shiro在項(xiàng)目中的使用(二)

在第一部分,使用shiro主要做了基于url的登陸攔截,但是在真正的生產(chǎn)環(huán)境下往往是注解,標(biāo)簽等綜合使用,以下是基于注解和標(biāo)簽的代碼筆記

URL攔截權(quán)限控制是基于過(guò)濾器或者攔截器的
方法注解權(quán)限控制是基于代理(action代理)

【1】spring配置中開(kāi)啟shiro注解

<!-- 開(kāi)啟shiro注解 -->
    <bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <!-- 強(qiáng)制使用cglib為Action創(chuàng)建代理對(duì)象() -->
        <property name="proxyTargetClass" value="true"></property>
    </bean>
    
    <!-- 切面類 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>

注意:這里最好開(kāi)啟cglib代理(產(chǎn)生的是子類對(duì)象),默認(rèn)是jdk代理(新的代理對(duì)象)

知識(shí)拓展:

1.JDK動(dòng)態(tài)代理
此時(shí)代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)了相同的接口

2.CGLIB代理
CGLIB(CODE GENERLIZE LIBRARY)代理是針對(duì)類實(shí)現(xiàn)代理,主要是對(duì)指定的類生成一個(gè)子類

具體查看:http://blog.csdn.net/cpzhong/article/details/6423333

另外注意:這里如果使用shiro了,在action中的baseAction就不能直接強(qiáng)轉(zhuǎn)了,因?yàn)槿绻莏dk代理是action的新代理對(duì)象,而非action對(duì)象或者子類對(duì)象,所以強(qiáng)轉(zhuǎn)會(huì)報(bào)錯(cuò),這也是為什么要使用cglib代理的原因。

【2】方法上使用權(quán)限注解

/**
     * 刪除派遣員
     * @return
     */
    @RequiresPermissions(value="staff11")//執(zhí)行當(dāng)前方法需要具有staff權(quán)限
    //@RequiresRoles(value="staff")//執(zhí)行當(dāng)前方法需要具有staff角色
    public String delete(){
        staffService.deleteBatch(ids);
        /**
         * 當(dāng)權(quán)限或者角色任意一個(gè)不滿足都會(huì)拋出org.apache.shiro.authz.UnauthorizedException: 
         * 異常,所以需要我們做公共異常捕獲,在struts配置文件中配置公共異常捕獲頁(yè)面
         */
        return "list";
    }

【3】Realm中授權(quán)
在bosReaml的授權(quán)方法中授予相應(yīng)權(quán)限

/**
     * 授權(quán)方法(這個(gè)用戶有什么權(quán)限)
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("進(jìn)入授權(quán)方法... ...");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("staff");//為當(dāng)前用戶授予staff權(quán)限
        
        //TODO 根據(jù)當(dāng)前登錄用戶查詢數(shù)據(jù)庫(kù),獲取其對(duì)應(yīng)的權(quán)限數(shù)據(jù)
        
        return info;
    }

【4】訪問(wèn)查看
(當(dāng)授權(quán)是staff11是會(huì)正常操作刪除方法,當(dāng)授權(quán)非staff11時(shí),我們分別授權(quán)staff11和staff,發(fā)現(xiàn)staff會(huì)報(bào)錯(cuò),拋出異常org.apache.shiro.authz.UnauthorizedException)

2017-08-24_114226.png

當(dāng)shiro使用注解時(shí),遇到權(quán)限和角色不足時(shí)均會(huì)拋出org.apache.shiro.authz.UnauthorizedException異常,所以這里需要捕獲處理
【5】struts中配置全局異常處理

<global-results>
            <result name="login">/login.jsp</result>
            <result name="unauthorizedUrl">/unauthorizedUrl.jsp</result>
        </global-results>
        <!-- 指定全局異常捕獲 -->
        <!-- 當(dāng)出現(xiàn)權(quán)限異常進(jìn)行捕獲,并返回至unauthorizedUrl.jsp--> 
        <global-exception-mappings>
            <exception-mapping result="unauthorizedUrl" 
                exception="org.apache.shiro.authz.AuthorizationException"></exception-mapping>
        </global-exception-mappings>
2017-08-24_114617.png

修改后

2017-08-24_114957.png

使用標(biāo)簽進(jìn)行資源控制
【1】jsp頁(yè)面引入shiro標(biāo)簽

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>  

【2】對(duì)需要權(quán)限攔截的菜單 按鈕進(jìn)行攔截添加
這里主要shiro標(biāo)簽可以直接包html代碼,也可以直接包js代碼

//工具欄(給刪除安全添加權(quán)限攔截)
    var toolbar = [ {
        id : 'button-view', 
        text : '查詢',
        iconCls : 'icon-search',
        handler : doView
    }, {
        id : 'button-add',
        text : '增加',
        iconCls : 'icon-add',
        handler : doAdd
    }, <shiro:hasPermission name="staff">{
        id : 'button-delete',
        text : '作廢',
        iconCls : 'icon-cancel',
        handler : doDelete
    },</shiro:hasPermission>{
        id : 'button-save',
        text : '還原',
        iconCls : 'icon-save',
        handler : doRestore
    }];

注意:<shiro:hasPermission name="staff11">表示只有擁有staff11權(quán)限的用戶才會(huì)顯示該按鈕

前后對(duì)比

2017-08-24_115649.png
2017-08-24_115611.png

【通過(guò)查詢數(shù)據(jù)庫(kù),進(jìn)行用戶授權(quán)】
修改自定義Realm的授權(quán)方法

/**
     * 授權(quán)方法(這個(gè)用戶有什么權(quán)限)
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("進(jìn)入授權(quán)方法... ...");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //info.addStringPermission("staff");//為當(dāng)前用戶授予staff權(quán)限
        //info.addRole("staff");//為當(dāng)前用戶授予staff角色(角色是權(quán)限的集合)  
        
        //TODO 根據(jù)當(dāng)前登錄用戶查詢數(shù)據(jù)庫(kù),獲取其對(duì)應(yīng)的權(quán)限數(shù)據(jù)
        //獲取當(dāng)前用戶
        User user = (User) principals.getPrimaryPrincipal();
        List<Function> list = null;
        if(user.getUsername().equals("admin")){
            //超級(jí)管理員(查詢所有權(quán)限)
            list = functionDao.findAll();
        }else{
            //普通用戶(查詢擁有權(quán)限)
            list = functionDao.findListByuserId(user.getId());
        }
        
        //授權(quán)
        for(Function function : list){
            info.addStringPermission(function.getCode());
        }
        return info;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容