posts - 193,  comments - 520,  trackbacks - 0
          一開始我把控制數(shù)據(jù)權(quán)限寫在業(yè)務(wù)里,以訂單管理為例,先討論一個最簡單的情況。管理員可以看所有的訂單,而用戶只能看自己的訂單。這里的管理員是一個角色。我會這么寫(一些次要代碼都省略了):

          ???List?getOrders(String?userId){
          ?????????????String?sql;
          ?????????????Role?role
          =orgService.getRoleForUser(userId);
          ?????????????
          if(("admin").equals(role.getName()))
          ???????????????????sql
          ="select?*?from?order";
          ?????????????
          else
          ???????????????????sql
          ="select?*?from?order?where?author="+userId;
          ?????????????Object?o
          =excuteSql(sql);
          ?????????????
          return?excute(o);
          ????????}

          恩,不錯,很好的完成了權(quán)限控制。過了沒多久,公司發(fā)展了,老板增加了人手,老板發(fā)話了,我要設(shè)置區(qū)域管理員分管不同區(qū)域的訂單。管理員分為北京地區(qū)管理員,上海地區(qū)管理員,其他地區(qū)管理員和總管理員。怎么辦?修改代碼吧
          ????List?getOrders(String?userId){
          ?????????????String?sql;
          ?????????????Role?role
          =orgService.getRoleForUser(userId);
          ?????????????
          if(("admin").equals(role.getName()))
          ??????????????????sql
          ="select?*?from?order";
          ?????????????
          else?if("bjadmin").equals(role.getName()))
          ?????????????????????????sql
          ="select?*?from?order?where?area='beijing'";
          ?????????????
          else?if("shadmin").equals(role.getName()))
          ?????????????????????????sql
          ="select?*?from?order?where?area='shanghai'";
          ?????????????
          else?if("qtadmin").equals(role.getName()))
          ?????????????????????????sql
          ="select?*?from?order?where?area='qita'";
          ?????????????
          else
          ???????????????????sql
          ="select?*?from?order?where?author="+userId;
          ?????????????Object?o
          =excuteSql(sql);
          ?????????????
          return?excute(o);
          ????????}

          恩恩,這就搞定了,可怎么也感覺不爽,也許該做點(diǎn)什么。一堆if/else權(quán)限判斷讓人心煩,再寫個類把這些sql管理起來好了,那就動手吧
          ??public?class?SqlManager{
          ??????????String?getSql(String?userId){
          ??????????????????String?sql;
          ??????????Role?role
          =orgService.getRoleForUser(userId);
          ??????????
          if(("admin").equals(role.getName()))
          ??????????????sql
          ="select?*?from?order";
          ??????????
          else?if("bjadmin").equals(role.getName()))
          ???????????????????sql
          ="select?*?from?order?where?area='beijing'";
          ??????????
          else?if("shadmin").equals(role.getName()))
          ???????????????????sql
          ="select?*?from?order?where?area='shanghai'";
          ??????????
          else?if("qtadmin").equals(role.getName()))
          ???????????????????sql
          ="select?*?from?order?where?area='qita'";
          ??????????
          else
          ????????????sql
          ="select?*?from?order?where?author="+userId;
          ??????????
          return?sql;
          ??????????}
          ??}

          這樣把權(quán)限判斷移到SqlManager里,業(yè)務(wù)代碼就清爽了很多,再增加管理員就修改SqlManager好了
          ????List?getOrders(String?userId){
          ?????????????String?sql
          =sqlManager.getSql(userId);
          ?????????????Object?o
          =excuteSql(sql);
          ?????????????
          return?excute(o);
          ????????}

          呵呵,看起來還不錯。但是等等,我們的業(yè)務(wù)方法為什么需要userId這個參數(shù)呢,是啊是啊,權(quán)限判斷用到了它,但是那和我業(yè)務(wù)又有什么關(guān)系呢,不爽。現(xiàn)在AOP不是很流行嗎,你不用AOP怎么能說明你技術(shù)高呢?快用吧快用吧,用不著也要想著方法用。
          業(yè)務(wù)方法簡化為
          ????List?getOrders(){
          ?????????????String?sql
          ="";
          ?????????????Object?o
          =excuteSql(sql);
          ?????????????
          return?excute(o);
          ????????}

          對excuteSql方法我們來AOP一下,注入權(quán)限判斷過的sql.嘿嘿,技術(shù)水平又一次得到了顯現(xiàn)。業(yè)務(wù)方法是簡單了,可我的SqlManager倒是復(fù)雜了,還是很不幸福。咋辦?用個配置文件吧,hibernate不是老鼓勵我們把sql寫在配置文件里嗎?
          ????<xml>
          ????????<sql?role
          ="admin">select?*?from?order</sql>
          ????????<sql?role
          ="bjadmin">select?*?from?order?where?area='beijing'</sql>
          ????????<sql?role
          ="shadmin">select?*?from?order?where?area='shanghai'</sql>
          ????????<sql?role
          ="qtadmin">select?*?from?order?where?area='qita'</sql>
          ????????<sql?role
          ="none">select?*?from?order?where?author=?</sql>
          ????</xml>

          這樣SqlManager就可以把行數(shù)縮小了,就可以敏捷一點(diǎn)了。
          ????public?class?SqlManager{
          ??????????String?getSql(String?userId){
          ??????????????????String?sql;
          ??????????Role?role
          =orgService.getRoleForUser(userId);
          ??????????sql
          =getSqlfromXml(role.getName());
          ??????????
          return?sql;
          ??????????}
          ??????????
          ??????????String?getSqlfromXml(String?rolename){
          ??????????????????.
          ??????????}
          ??}

          以后再增加權(quán)限連類都不用修改了,改xml好了。等等,你是不是把問題太簡單化了。現(xiàn)在不僅僅是訂單,貨物也要這么分區(qū)域管理。
          不錯,我們應(yīng)該想著通用一下了。這樣,把SqlManager抽象一下
          ????????String?abstract?getSqlfromXml(String?rolename);

          然后做幾個子類好了 OrderSqlManager, GoodsSqlManager .
          可是,哥們,書上說,要面向接口編程,你這樣不太好吧。沒事,再接口一下:
          ???public?interface?SqlManagerInterface{
          ???????????String?getSql(String?userId);
          ???}

          還是沒法用啊。也許現(xiàn)在可以看看acegi的provider機(jī)制了,把這一大堆SqlManager全部作為provider,根據(jù)不同的模塊選擇不同的provider,統(tǒng)一攔截excuteSql方法,生成不同的sql到數(shù)據(jù)庫執(zhí)行。xml不爽?db也可以。然后,再然后呢?改你的類名,重構(gòu),和acegi整合一下。
          呵呵,完全是個人的一些想法,希望多批評提提意見。我想表達(dá)的意思是:也許把數(shù)據(jù)權(quán)限再抽象一些,以組件的形式來減少侵入是可以做到的。

          http://www.aygfsteel.com/ronghao 榮浩原創(chuàng),轉(zhuǎn)載請注明出處:)
          posted on 2007-03-23 18:35 ronghao 閱讀(6721) 評論(6)  編輯  收藏 所屬分類: 權(quán)限相關(guān)

          FeedBack:
          # re: 對數(shù)據(jù)權(quán)限控制的實(shí)驗(yàn)
          2007-03-24 23:21 | 龍卷風(fēng)驛站
          比較適合講知識,文筆不錯,贊一個  回復(fù)  更多評論
            
          # re: 對數(shù)據(jù)權(quán)限控制的實(shí)驗(yàn)[未登錄]
          2007-03-26 10:15 | 阿蜜果
          你的權(quán)限篇寫得不錯,up!  回復(fù)  更多評論
            
          # re: 對數(shù)據(jù)權(quán)限控制的實(shí)驗(yàn)
          2007-03-29 10:52 | jerome
          講的不錯,淺顯易懂,深有收獲啊  回復(fù)  更多評論
            
          # re: 對數(shù)據(jù)權(quán)限控制的實(shí)驗(yàn)[未登錄]
          2007-10-11 15:29 | MagicYang
          我看到第3段代碼就聯(lián)想到:
          1、先把if/else if換成switch語句;
          2、再用多態(tài)替換switch語句;
          用戶接口:
          public interface User{
          public abstract List getOrders();
          }

          普通用戶:
          public abstract class User implements User{
          public List getOrders(String userId){
          sql="select * from order where author="+userId;
          Object o=excuteSql(sql);
          return execute(o);
          }
          }

          管理員:
          public abstract class Administrator implements User{
          public List getOrders(String adminId){
          sql="select * from order where area=" + getAreaByAdmin();
          Object o=excuteSql(sql);
          return execute(o);
          }

          protected abstract String getAreaByAdmin();
          }

          北京地區(qū)管理員:
          public class BjAdministractor extends Administractor{
          protected String getAreaByAdmin(){
          return "beijing";
          }
          }

          除了訂單,如果貨物也要加入?yún)^(qū)域管理的話- -!,只需要在普通用戶和管理員兩個抽象類中加入相關(guān)的抽象方法,具體的區(qū)域管理員里各自實(shí)現(xiàn)他們就行了。我的方法是不是很土。。。  回復(fù)  更多評論
            
          # re: 對數(shù)據(jù)權(quán)限控制的實(shí)驗(yàn)[未登錄]
          2007-10-11 15:34 | MagicYang
          e...好象User類和User接口重名了  回復(fù)  更多評論
            
          # re: 對數(shù)據(jù)權(quán)限控制的實(shí)驗(yàn)[未登錄]
          2007-10-11 15:39 | MagicYang
          以上只是基于你的數(shù)據(jù)權(quán)限控制實(shí)驗(yàn)的所做重構(gòu),一般來說不傾向這么做,只把sql的area查詢條件作參數(shù)傳遞就行了,你不用這么多xml,我也不用這么多子類。。。不過我覺得這只是你的一個實(shí)驗(yàn)例子而已對吧  回復(fù)  更多評論
            
          <2007年3月>
          25262728123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          關(guān)注工作流和企業(yè)業(yè)務(wù)流程改進(jìn)。現(xiàn)就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

          常用鏈接

          留言簿(38)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          常去的網(wǎng)站

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 南溪县| 靖西县| 昔阳县| 资阳市| 江西省| 财经| 乌拉特中旗| 新安县| 简阳市| 自贡市| 武定县| 乌拉特前旗| 余姚市| 金坛市| 清苑县| 伊宁县| 罗平县| 黄石市| 古田县| 通州区| 成都市| 肥西县| 香格里拉县| 石阡县| 浦江县| 贡山| 罗山县| 定边县| 清丰县| 甘谷县| 临澧县| 林西县| 锦屏县| 读书| 四子王旗| 汶上县| 巩义市| 东兴市| 梁河县| 永仁县| 桂平市|