web开发中的权限设计拙见一二(3) ----资源配置与权限判断

在上文中我们提到了一个资源对应一个数据库表,在T_ResourceInfo表中我们也提到了有一个字段专门来记录表名,然后我书写一个资源配置文件,用来配置我的业务类与资源的对应关系,代码如下:
1 <? xml version="1.0" encoding="GB2312" ?>
2 < data >
3      < mapping  SysName ="s" >
4          < module  BusinessClass ="com.ideal.framework.business.businessface.IBLogin"  TableName ="user_info" />
5      </ mapping >
6 </ data >
其中BusinessClass代表业务接口,TableName代表该业务接口所要操作的数据实体(数据表),此处的TableName必须与T_ResourceInfo中的Module_Code一致。
用户登录后,需要操作T_UserInfo这个表时,我们的逻辑将会把请求带入IBLogin这个业务逻辑中,在我们的AOP模块中,可以用MethodInterceptor来截获当前用户想要操作的业务逻辑,当AOP模块截获了用户的请求,并判断用户想要操作IBLogin这个业务逻辑,它将在上述的mapping文件中去找该业务逻辑对应的资源user_info,然后去资源表中判断该用户是否有操作user_info的权限。
(注:上述xml文件在系统初始化时候加载入内存中,我们也可以将权限信息也加载在内存中,不会很大,一切资源在内存中操作,非常快)
下面我贴点代码,在系统初始化时:
 1 package  com.ideal.framework;
 2
 3 import  java.util. * ;
 4 import  java.sql. * ;
 5 import  com.ideal.framework.dao.daoface. * ;
 6 import  com.ideal.framework.po. * ;
 7
 8 public   class  ResourceContainer
 9 {
10    public static boolean change_resource; //更新资源  系统持久
11    public static Vector resource_container = new Vector(); //资源容器  用户持久
12    private IUserRoleDAO m_user_role_dao;
13    private IRoleResourceDAO m_role_resource_dao;
14    private IUserDAO m_user_dao;
15
16    public ResourceContainer()
17{
18    }

19
20    public void setUserResource()
21    {
22        System.out.println("initialize resource:");
23        List user_list = m_user_dao.getAllUser();
24        for (int i = 0; i < user_list.size(); i++)
25        {
26            UserInfo user = (UserInfo) user_list.get(i);
27            List role_list = m_user_role_dao.getRoleInfo(user);
28            for (int j = 0; j < role_list.size(); j++)
29            {
30                RoleInfo role = (RoleInfo) role_list.get(j);
31                List resource_list = m_role_resource_dao.
32                    getResourceInfo(role);
33                for (int k = 0; k < resource_list.size(); k++)
34                {
35                    Hashtable hash = new Hashtable();
36                    hash.put(user.getLoginId(), resource_list.get(k));
37                    hash.put("Unit_"+user.getLoginId(), user.getUnit());
38                    hash.put("Role_"+user.getLoginId(), role.getRoleName());
39                    ResourceContainer.resource_container.add(hash);
40                }

41            }

42        }

43    }

44
45    public Vector getResource_container()
46    {
47        return resource_container;
48    }

49
50    public void setResource_container(Vector resource_container)
51    {
52        this.resource_container = resource_container;
53    }

54
55    public IRoleResourceDAO getM_role_resource_dao()
56    {
57        return m_role_resource_dao;
58    }

59
60    public IUserDAO getM_user_dao()
61    {
62        return m_user_dao;
63    }

64
65    public IUserRoleDAO getM_user_role_dao()
66    {
67        return m_user_role_dao;
68    }

69
70    public void setM_role_resource_dao(IRoleResourceDAO m_role_resource_dao)
71    {
72        this.m_role_resource_dao = m_role_resource_dao;
73    }

74
75    public void setM_user_dao(IUserDAO m_user_dao)
76    {
77        this.m_user_dao = m_user_dao;
78    }

79
80    public void setM_user_role_dao(IUserRoleDAO m_user_role_dao)
81    {
82        this.m_user_role_dao = m_user_role_dao;
83    }

84
85    public void setChange_resource(boolean change_resource)
86    {
87        this.change_resource = change_resource;
88    }

89
90    public boolean isChange_resource()
91    {
92        return change_resource;
93    }

94}

95
将用户对应的角色,资源信息加载如内存,另外在初始化时候的xml文件的树形结构也加载入内存,这边就不贴代码了
下面是AOP模块的advice代码:
package  com.ideal.framework.sys.advice;

/** */ /**
 * <p>Title: BusinessAccessAdvisor</p>
 * <p>Description: 业务模块AOP权限监听器</p>
 * <p>Copyright: Copyright (c) 2006</p>
 * <p>Company: ideal</p>
 * 
@author alex
 * 
@version 1.0
 
*/


import  org.aopalliance.intercept.MethodInterceptor;
import  org.aopalliance.intercept.MethodInvocation;
import  com.ideal.framework.InitResource;
import  com.ideal.framework.util.XMLUtil;
import  java.util.ArrayList;
import  java.util.Hashtable;
import  com.ideal.framework.sys.accesscontrol.GenericAccessBase;
import  java.lang.reflect.Field;
import  com.ideal.framework.po. * ;
import  java.lang.reflect.Method;
import  java.util. * ;
import  java.io. * ;
import  javax.servlet.http.HttpServletRequest;

public   class  BusinessAccessAdvisor
    
implements  MethodInterceptor
{

    
public BusinessAccessAdvisor()
    
{
    }


    
public Object invoke(MethodInvocation invocation) throws
        Throwable
    
{
        String user_name 
= "";
        Object obj 
= invocation.getArguments()[1];
        
if (obj instanceof HttpServletRequest)
    
{
            HttpServletRequest request 
= (HttpServletRequest)obj;
            user_name 
= (String)request.getSession().getAttribute("UserName");//取出用户名
        }

        String bean_name 
= invocation.getMethod().getDeclaringClass().getName();//取出用户想要操作的业务逻辑
        XMLUtil xml 
= (XMLUtil) InitResource.context.getBean("XMLUtil");
        ArrayList list 
= xml.getFieldList("mapping""s", xml.doc);
        
for (int i = 0; i < list.size(); i++)
    
{
            Hashtable hash 
= (Hashtable) list.get(i);
            
if (hash.get("BusinessClass").equals(invocation.getMethod().//判断用户是否有权操作该业务逻辑所对应表
                                                 getDeclaringClass().getName()))
        
{
                String table_name 
= (String) hash.get("TableName");
                GenericAccessBase access_controller 
= (GenericAccessBase)
                    InitResource.context.getBean(
"GenericAccessBase");
                
if (access_controller.CheckAccessPrivilege(user_name, table_name))//若用户有权操作该表,则让程序进入业务逻辑
            
{
                    
return invocation.proceed();
                }

            }

        }

        System.out.println(
"no permission .reject by " + bean_name);
        
return null;
    }

}

下面是判断用户是否具有操作该表权限的类:
 1 package  com.ideal.framework.sys.accesscontrol;
 2
 3 import  com.ideal.framework.InitResource;
 4 import  com.ideal.framework.util.XMLUtil;
 5 import  com.ideal.framework.po.UserInfo;
 6 import  com.ideal.framework.ResourceContainer;
 7 import  java.util. * ;
 8 // import com.ideal.framework.po.ResourceInfo;
 9
10 public   class  GenericAccessBase
11 {
12    UserInfo user;
13
14    public GenericAccessBase()
15    {
16    }

17
18    public void setUser(UserInfo user)
19    {
20        this.user = user;
21    }

22
23    public boolean CheckAccessPrivilege(String user_name, String table_name)
24    {
25        for (int i = 0; i < ResourceContainer.resource_container.size(); i++)
26        {
27            Hashtable temp_hash = (Hashtable)ResourceContainer.resource_container.get(i);//从内存中取出用户资源信息
28            if (temp_hash.containsKey(user_name))
29            {
30                ResourceInfo resource = (ResourceInfo)temp_hash.get(user_name);
31                if (table_name.trim().toLowerCase().equals(resource.getModuleCode().trim().toLowerCase()))//比对用户拥有的资源和当前的table_name
32                {
33                    return true;
34                }

35            }

36        }

37        return false;
38    }

39}

40
ok,到此为止,我们的底层拦截就完成了,接下来就是界面权限处理,界面权限比较复杂,因为用户可能具有添加权限,没有上传权限,有下载权限却没有更新权限等,情况很复杂,所以我们这边必须有一个判断当前用户是否具有这些复杂权限的类:
  1 package  com.ideal.framework.sys.privilege;
  2
  3 /** */ /**
  4 * <p>Title: GenericPrivilegeBase</p>
  5 * <p>Description: 通用权限法则</p>
  6 * <p>Copyright: Copyright (c) 2006</p>
  7 * <p>Company: ideal</p>
  8 * @author alex
  9 * @version 1.0
 10 */

 11
 12 public   class  GenericPrivilegeBase
 13 {
 14    public final static int NO_PRIVILEGE = 0;
 15    public final static int QUERY_OR_USE_PRIVILEGE = 1;//察看权限
 16    public final static int CREATE_PRIVILEGE = 2;//添加权限
 17    public final static int DELETE_PRIVILEGE = 4;//删除权限
 18    public final static int UPDATE_PRIVILEGE = 8;//更新权限
 19    public final static int ALL_PRIVILEGE = QUERY_OR_USE_PRIVILEGE |
 20        CREATE_PRIVILEGE | DELETE_PRIVILEGE | UPDATE_PRIVILEGE;//增删改查权限
 21
 22    public GenericPrivilegeBase()
 23    {
 24    }

 25
 26    public static boolean isValidPrivilege(int privilege)//判断是否具有权限
 27    {
 28        if ( (privilege & QUERY_OR_USE_PRIVILEGE) != 0)
 29        {
 30            return true;
 31        }

 32
 33        if ( (privilege & CREATE_PRIVILEGE) != 0)
 34        {
 35            return true;
 36        }

 37
 38        if ( (privilege & DELETE_PRIVILEGE) != 0)
 39        {
 40            return true;
 41        }

 42
 43        if ( (privilege & UPDATE_PRIVILEGE) != 0)
 44        {
 45            return true;
 46        }

 47
 48        return false;
 49    }

 50
 51    public static boolean checkQueryPrivilege(int privilege)//判断是否具有察看权限
 52    {
 53        if ( (privilege & QUERY_OR_USE_PRIVILEGE) != 0)
 54        {
 55            return true;
 56        }

 57        else
 58        {
 59            return false;
 60        }

 61    }

 62
 63    public static boolean checkUsePrivilege(int privilege)
 64    {
 65        if ( (privilege & QUERY_OR_USE_PRIVILEGE) != 0)
 66        {
 67            return true;
 68        }

 69        else
 70        {
 71            return false;
 72        }

 73    }

 74
 75    public static boolean checkCreatePrivilege(int privilege)//判断是否有添加权限
 76    {
 77        if ( (privilege & CREATE_PRIVILEGE) != 0)
 78        {
 79            return true;
 80        }

 81        else
 82        {
 83            return false;
 84        }

 85    }

 86
 87    public static boolean checkDeletePrivilege(int privilege)//判断是否有删除权限
 88    {
 89        if ( (privilege & DELETE_PRIVILEGE) != 0)
 90        {
 91            return true;
 92        }

 93        else
 94        {
 95            return false;
 96        }

 97    }

 98
 99    public static boolean checkUpdatePrivilege(int privilege)
100    {
101        if ( (privilege & UPDATE_PRIVILEGE) != 0)
102        {
103            return true;
104        }

105        else
106        {
107            return false;
108        }

109    }

110}

111
然后我们自定义两个标签,Privilege与noPrivilege用来判断用户是否具有权限,这两个标签必须具有三个基本的attribute,beanName:当前所要操作的哪个资源;scope:用户信息存放在哪个域;operation:用户想要进行什么操作
贴一个privilege标签的代码:
  1 package  com.ideal.framework.tag;
  2
  3 import  javax.servlet.jsp.tagext.BodyTagSupport;
  4 import  javax.servlet.jsp.tagext. * ;
  5 import  javax.servlet.http. * ;
  6 import  javax.servlet.jsp. * ;
  7 import  java.sql. * ;
  8 import  java.io. * ;
  9 import  com.ideal.framework. * ;
 10 import  com.ideal.framework.po.ResourceInfo;
 11 import  java.util.Hashtable;
 12 import  com.ideal.framework.sys.privilege.GenericPrivilegeBase;
 13
 14 public   class  PrivilegeTag
 15      extends  BodyTagSupport
 16 {
 17    String operation;
 18    private String beanName;
 19    private String scope;
 20
 21    public PrivilegeTag()
 22    {
 23        super();
 24    }

 25
 26    public void setOperation(String operation)
 27    {
 28        this.operation = operation;
 29    }

 30
 31    public void setBeanName(String beanName)
 32    {
 33        this.beanName = beanName;
 34    }

 35
 36    public void setScope(String scope)
 37    {
 38        this.scope = scope;
 39    }

 40
 41    public int doStartTag() throws JspTagException
 42    {
 43        if (scope == null || scope.equals(""))
 44            return SKIP_BODY;
 45        else
 46        {
 47            String user_name = "";
 48            if (scope.equalsIgnoreCase("session"))
 49            {
 50                HttpSession session = pageContext.getSession();
 51                user_name = (String) session.getAttribute("UserName");
 52            }

 53            else
 54            {
 55                HttpServletRequest request = (HttpServletRequest) pageContext.
 56                    getRequest();
 57                user_name = (String) request.getAttribute("UserName");
 58            }

 59
 60            for (int i = 0; i < ResourceContainer.resource_container.size(); i++)
 61            {
 62                Hashtable temp_hash = (Hashtable) ResourceContainer.
 63                    resource_container.get(i);
 64                if (temp_hash.containsKey(user_name))
 65                {
 66                    ResourceInfo resource = (ResourceInfo) temp_hash.get(
 67                        user_name);
 68                    if (beanName.trim().toLowerCase().equals(resource.
 69                        getModuleCode().trim().toLowerCase()))
 70                    {
 71                        if(this.checkPrivilege(resource.getPrivilegeCode()) == EVAL_BODY_TAG)
 72                            return EVAL_BODY_TAG;
 73                    }

 74                }

 75            }

 76
 77        }

 78        return SKIP_BODY;
 79return EVAL_BODY_TAG;
 80    }

 81
 82    public int checkPrivilege(String privilege)
 83    {
 84        int int_privilege = 0;
 85        try
 86        {
 87            int_privilege = Integer.parseInt(privilege);
 88        }

 89        catch (NumberFormatException ex)
 90        {
 91            System.out.println(ex.getMessage());
 92        }

 93        GenericPrivilegeBase gpb = new GenericPrivilegeBase();
 94        if (operation.equals("NONE"))
 95            return EVAL_BODY_TAG;
 96        if (operation.equals("QUERY"))
 97            if (gpb.checkQueryPrivilege(int_privilege))
 98                return EVAL_BODY_TAG;
 99        if (operation.equals("CREATE"))
100            if (gpb.checkCreatePrivilege(int_privilege))
101                return EVAL_BODY_TAG;
102        if (operation.equals("DELETE"))
103            if (gpb.checkDeletePrivilege(int_privilege))
104                return EVAL_BODY_TAG;
105        if (operation.equals("UPDATE"))
106            if (gpb.checkUpdatePrivilege(int_privilege))
107                return EVAL_BODY_TAG;
108        if (operation.equals("USE"))
109            if (gpb.checkUsePrivilege(int_privilege))
110                return EVAL_BODY_TAG;
111        return SKIP_BODY;
112    }

113
114    public int doAfterBody() throws JspTagException
115    {
116        return SKIP_BODY;
117    }

118
119    public int doEndTag() throws JspTagException
120    {
121        try
122        {
123            if (bodyContent != null)
124            {
125                bodyContent.writeOut(bodyContent.getEnclosingWriter());
126            }

127        }

128        catch (IOException ex)
129        {
130            throw new JspTagException("IO Error:" + ex.getMessage());
131        }

132        return EVAL_PAGE;
133    }

134
135    public void doInitBody() throws JspTagException
136    {
137    }

138
139    public void setBodyContent(BodyContent bodyContent)
140    {
141        this.bodyContent = bodyContent;
142    }

143}

144
在页面上,我们如此使用该标签:
1 < privilege  beanName ="user_info"  scope ="session"  operation ="create" >
2      < input  type ="button"  value ="添加" >
3 </ privilege >

如此,系统会自动根据当前session中的用户来判断是否需要显示当前的添加按钮。
到此所有权限的代码完成,在此套权限设计中,我始终抱着AOP的想法:让他属于一个系统切面,以后再开发其他系统时,作为一个模块就可以加载上去,与系统无关

你可能感兴趣的:(web开发中的权限设计拙见一二(3) ----资源配置与权限判断)