在上文中我们提到了一个资源对应一个数据库表,在T_ResourceInfo表中我们也提到了有一个字段专门来记录表名,然后我书写一个资源配置文件,用来配置我的业务类与资源的对应关系,代码如下:
用户登录后,需要操作T_UserInfo这个表时,我们的逻辑将会把请求带入IBLogin这个业务逻辑中,在我们的AOP模块中,可以用MethodInterceptor来截获当前用户想要操作的业务逻辑,当AOP模块截获了用户的请求,并判断用户想要操作IBLogin这个业务逻辑,它将在上述的mapping文件中去找该业务逻辑对应的资源user_info,然后去资源表中判断该用户是否有操作user_info的权限。
(注:上述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;
}
}
下面是判断用户是否具有操作该表权限的类:
贴一个privilege标签的代码:
如此,系统会自动根据当前session中的用户来判断是否需要显示当前的添加按钮。
到此所有权限的代码完成,在此套权限设计中,我始终抱着AOP的想法:让他属于一个系统切面,以后再开发其他系统时,作为一个模块就可以加载上去,与系统无关
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一致。
2
3
4
5
6
用户登录后,需要操作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文件的树形结构也加载入内存,这边就不贴代码了
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
下面是AOP模块的advice代码:
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,到此为止,我们的底层拦截就完成了,接下来就是界面权限处理,界面权限比较复杂,因为用户可能具有添加权限,没有上传权限,有下载权限却没有更新权限等,情况很复杂,所以我们这边必须有一个判断当前用户是否具有这些复杂权限的类:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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:用户想要进行什么操作
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
贴一个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;
79
return 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
在页面上,我们如此使用该标签:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
1
<
privilege
beanName
="user_info"
scope
="session"
operation
="create"
>
2
<
input
type
="button"
value
="添加"
>
3
</
privilege
>
2
3
如此,系统会自动根据当前session中的用户来判断是否需要显示当前的添加按钮。
到此所有权限的代码完成,在此套权限设计中,我始终抱着AOP的想法:让他属于一个系统切面,以后再开发其他系统时,作为一个模块就可以加载上去,与系统无关