一个客户系统最基本的功能是对客户的创建,修改,删除和查询。实现这样的功能通常是在数据库中建一个Customer表,然后通过程序实现以上基本功能。在一个个人环境的应用中,一个用户可以对所有的客户进行任意操作,基本不存在权限控制问题。在多用户系统中,客户属于一个人或者一群人,而对客户的操作权限也不可能是人人一样。所以需要对用户的操作做权限控制。
这里有必要先对权限控制方式本身做一下讨论,有些系统用菜单进行权限控制,比如"新建客户","浏览客户",往往用操作名加上一个资源名代表一个权限,这样的权限控制有一个缺陷,就是一般漏掉了一个资源范围,比如浏览什么样的客户,就没有说明。当然也可以加上,比如浏览个人客户,浏览部门客户,浏览公司客户,但是随着需要控制资源类型的增加,通过不断增加菜单项来进行控制,并不是一个很好的方法。在B/S系统中的菜单控制,有2重意义,一是真正的菜单,没有权限的用户就看不到相应的菜单项,另外一个为了防止用户任意提交信息,在服务器端对用户提交的URL进行检查,看是不是有这个权限。比如对于用户请求的ListCus.do就要先检查用户是否有访问这个URL的权限:
public class ListCusAction extends Action{ ... public ActionForward execute(...){ ... //必须提供这样的检查的方法。 PermitUtil.checkPermit(userID,url); list = dao.query(sql); ... } } |
作为客户系统最简单的一种考虑,是每个用户管理自己的客户。这种请况下,我们通过在Customer表中增加一个用户字段,就可以知道这个客户对应于哪一个用户。如下面的类所示:
public class Customer{ private String ctmNo; private String ctmName; ... private String userID; //getters and setters } |
public class DelCusAction extends Action{ ... public ActionForward execute(...){ ... //必须提供这样的检查的方法。 dao.checkPermit(customer,userID); dao.delete(customer); ... } } |
现在我们接触一个更复杂一点的需求,就是客户转移,把客户从一个用户,指派给另外一个用户。在上面的实现基础上,只要添加一个接口,改变客户所属的用户,问题也就解决了。如下:
public class ChangeUserAction extends Action{ ... public ActionForward execute(...){ ... dao.checkPermit(customer,userID); //改变客户所属用户到newUserID。 dao.changeUser(customer,newUserID); ... } } |
每个用户现在可以管理自己的客户,也可以把客户交给别人管理,问题解决得完美。我们再考虑实际的情况,一个客户可能可以被一个用户看,但是不可以被修改或者删除。我们怎么控制这样的权限,加一个菜单项-"察看客户",用户A可以执行这个操作,但是不可以选择菜单项-"修改客户",针对每一个动作,我们加了一个菜单项。我们需要控制的内容变得越来越多。再深入分析,可以发现,其实上面的方案已经不能满足需求。 2个客户我们如何知道一个可以被用户A看,一个不可以,出现了一个资源的管理问题,必须有另外的方案来进行这种权限的控制。我们设计一个资源类:
public class CustomerResource{ //客户编号 private String ctmNo; //操作类型 private String action; //用户 private String userID; //setters and getters. } |
public class CustomerResourceManager{ private static List resources; private static void addResources(CustomerResource resource){ resources.add(resource); } //从数据库装载相应用户的客户操作权限。 private static void retrieveResources(String userID){ ... } //检查相应的权限是否在resources中存在。 private static boolean checkPermit(CustomerResource permit){ ... } } |
public class DelCusAction extends Action{ ... public ActionForward execute(...){ ... //必须提供这样的检查的方法。 CustomerResource resource = new CustomerResource(); resource.setCtmNo(customer.getCtmNo()); resource.setAction("DELETE"); resource.setUserID(userID); if(CustomerResourceManager.checkPermit(resource)){ dao.delete(customer); } ... } } |