posts - 193,  comments - 520,  trackbacks - 0
一开始我把控制数据权限写在业务里,以订单管理为例,先讨论一个最简单的情况。管理员可以看所有的订单,而用户只能看自己的订单。这里的管理员是一个角色。我会这么写(一些次要代码都省略了):

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

恩,不错,很好的完成了权限控制。过了没多久,公司发展了,老板增加了人手,老板发话了,我要设置区域管理员分管不同区域的订单。管理员分为北京地区管理员,上海地区管理员,其他地区管理员和总管理员。怎么办?修改代码吧
    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);
        }

恩恩,这就搞定了,可怎么也感觉不爽,也许该做点什么。一堆if/else权限判断让人心烦,再写个类把这些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;
          }
  }

这样把权限判断移到SqlManager里,业务代码就清爽了很多,再增加管理员就修改SqlManager好了
    List getOrders(String userId){
             String sql
=sqlManager.getSql(userId);
             Object o
=excuteSql(sql);
             
return excute(o);
        }

呵呵,看起来还不错。但是等等,我们的业务方法为什么需要userId这个参数呢,是啊是啊,权限判断用到了它,但是那和我业务又有什么关系呢,不爽。现在AOP不是很流行吗,你不用AOP怎么能说明你技术高呢?快用吧快用吧,用不着也要想着方法用。
业务方法简化为
    List getOrders(){
             String sql
="";
             Object o
=excuteSql(sql);
             
return excute(o);
        }

对excuteSql方法我们来AOP一下,注入权限判断过的sql.嘿嘿,技术水平又一次得到了显现。业务方法是简单了,可我的SqlManager倒是复杂了,还是很不幸福。咋办?用个配置文件吧,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就可以把行数缩小了,就可以敏捷一点了。
    public class SqlManager{
          String getSql(String userId){
                  String sql;
          Role role
=orgService.getRoleForUser(userId);
          sql
=getSqlfromXml(role.getName());
          
return sql;
          }
          
          String getSqlfromXml(String rolename){
                  .
          }
  }

以后再增加权限连类都不用修改了,改xml好了。等等,你是不是把问题太简单化了。现在不仅仅是订单,货物也要这么分区域管理。
不错,我们应该想着通用一下了。这样,把SqlManager抽象一下
        String abstract getSqlfromXml(String rolename);

然后做几个子类好了 OrderSqlManager, GoodsSqlManager .
可是,哥们,书上说,要面向接口编程,你这样不太好吧。没事,再接口一下:
   public interface SqlManagerInterface{
           String getSql(String userId);
   }

还是没法用啊。也许现在可以看看acegi的provider机制了,把这一大堆SqlManager全部作为provider,根据不同的模块选择不同的provider,统一拦截excuteSql方法,生成不同的sql到数据库执行。xml不爽?db也可以。然后,再然后呢?改你的类名,重构,和acegi整合一下。
呵呵,完全是个人的一些想法,希望多批评提提意见。我想表达的意思是:也许把数据权限再抽象一些,以组件的形式来减少侵入是可以做到的。

http://www.blogjava.net/ronghao 荣浩原创,转载请注明出处:)
posted on 2007-03-23 18:35 ronghao 阅读(6705) 评论(6)  编辑  收藏 所属分类: 权限相关

FeedBack:
# re: 对数据权限控制的实验
2007-03-24 23:21 | 龙卷风驿站
比较适合讲知识,文笔不错,赞一个  回复  更多评论
  
# re: 对数据权限控制的实验[未登录]
2007-03-26 10:15 | 阿蜜果
你的权限篇写得不错,up!  回复  更多评论
  
# re: 对数据权限控制的实验
2007-03-29 10:52 | jerome
讲的不错,浅显易懂,深有收获啊  回复  更多评论
  
# re: 对数据权限控制的实验[未登录]
2007-10-11 15:29 | MagicYang
我看到第3段代码就联想到:
1、先把if/else if换成switch语句;
2、再用多态替换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();
}

北京地区管理员:
public class BjAdministractor extends Administractor{
protected String getAreaByAdmin(){
return "beijing";
}
}

除了订单,如果货物也要加入区域管理的话- -!,只需要在普通用户和管理员两个抽象类中加入相关的抽象方法,具体的区域管理员里各自实现他们就行了。我的方法是不是很土。。。  回复  更多评论
  
# re: 对数据权限控制的实验[未登录]
2007-10-11 15:34 | MagicYang
e...好象User类和User接口重名了  回复  更多评论
  
# re: 对数据权限控制的实验[未登录]
2007-10-11 15:39 | MagicYang
以上只是基于你的数据权限控制实验的所做重构,一般来说不倾向这么做,只把sql的area查询条件作参数传递就行了,你不用这么多xml,我也不用这么多子类。。。不过我觉得这只是你的一个实验例子而已对吧  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问  
 
<2007年3月>
25262728123
45678910
11121314151617
18192021222324
25262728293031
1234567

关注工作流和企业业务流程改进。现就职于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

常用链接

留言簿(38)

随笔分类

随笔档案

文章分类

文章档案

常去的网站

搜索

  •  

最新评论

阅读排行榜

评论排行榜