如何解决网站多用户权限管理

   通过URL匹配控制访问权限,也就是在用户请求(response)某个URL的时候,查看该用户是否有这个权限。这个“查看”是在一个Filter中进行的。判断用户是否有权限的标准是在一个xml文件中配置的。Dtd文档如下

   如:Java代码 
1.<?xml version="1.0" encoding="UTF-8"?>  
2. 
3. 
4.<!ELEMENT privilege (globe-error?,allmapping,user-name,mapping*)>  
5.<!ELEMENT globe-error (#PCDATA)>  
6.<!ELEMENT allmapping (#PCDATA)>  
7.<!ELEMENT user-name (#PCDATA)>  
8.<!ELEMENT mapping (error?, message)>  
9.<!ELEMENT error (#PCDATA)>  
10.<!ELEMENT message (#PCDATA)>  
11. 
12.<!ATTLIST globe-error redirect (false|true) "false">  
13.<!ATTLIST error redirect (false|true) "false">  
14.<!ATTLIST mapping   
15.    name CDATA #REQUIRED  
16.    url CDATA #REQUIRED   
17.    code CDATA #REQUIRED>  
18.<!ATTLIST message key CDATA #IMPLIED > 
<?xml version="1.0" encoding="UTF-8"?>

  <!ELEMENT privilege (globe-error?,allmapping,user-name,mapping*)>
<!ELEMENT globe-error (#PCDATA)>
<!ELEMENT allmapping (#PCDATA)>
<!ELEMENT user-name (#PCDATA)>
<!ELEMENT mapping (error?, message)>
<!ELEMENT error (#PCDATA)>
<!ELEMENT message (#PCDATA)>

<!ATTLIST globe-error redirect (false|true) "false">
<!ATTLIST error redirect (false|true) "false">
<!ATTLIST mapping
 name CDATA #REQUIRED
    url CDATA #REQUIRED
    code CDATA #REQUIRED>
<!ATTLIST message key CDATA #IMPLIED >

Xml文档的核心是mapping元素,有url,code属性(必选)和error,message子元素。url表示匹配的URL,code是 权限码,当用户的权限码符合这里的配置的权限码时,就认为用户用权限访问该URL,name属性唯一表示一个mapping。allmapping元素是 的内容所有mapping元素name的集合,每个name之间用一个符号隔开,比如’|’或’,’都可以,用来帮助自动生成权限码,后面详细说明。 Error(可选,如果没有则使用globe-error)是用户无权限时显示的错误页面,redirect属性(可选)制定forward到错误页面还 是redirect到forward页面。message指定返回的错误信息(支持国际化)。

用户的权限码存放在用户的session中,由于我习惯上把用户信息放在一个User对象中,再保存到session中,所以这里我的想法是User对象中有个属性表示用户权限码,比如可以这样获取:

Java代码 
1.pcode=(User)session.getAttribute("user").getCode();//pcode就是用户权限码 
pcode=(User)session.getAttribute("user").getCode();//pcode就是用户权限码

下面就开始说权限是如何设定的了。
 
先说说linux的文件权限设定,比如设定一个文件的权限111010010(所有者读写执行,同组读,其他人读),用了三组三位的二进制数,第一组是文 件所有者,第二组是和所有者在同一组的用户,第三组是和所有者没有任何关系的其他人。每一组中,第一位表示“读”的权限,第二位表示“写”的权限,第三位 表示“执行”的权限。好,我们的权限表示方法也出现了,allmapping元素的作用也显示出来了。allmapping中有n的mapping设 定,mapping中name出现的顺序是有意义的,不过开发者不用关心它的顺序,让大家注意顺序是为了下面说明的更方便点。例如:

Java核心代码 
1.<allmapping>read|add|delete<allmapping>  
2.<mapping name=”read” url=”/read.do”>  
3.    <error>/errorpage.jsp</error>  
4.    <message key=”error.read”>没有权限读取的信息</message>  
5.</mapping>  
6.<mapping name=”add” url=”/add.do”>  
7.    <error>/errorpage.jsp</error>  
8.    <message key=”error.add”>没有权限添加的信息</message>  
9.</mapping>  
10.<mapping name=”delete” url=”/delete.do”>  
11.    <error>/errorpage.jsp</error>  
12.    <message key=”error.delete”>没有权限删除的信息</message>  
13.</mapping> 
<allmapping>read|add|delete<allmapping>
<mapping name=”read” url=”/read.do”>
 <error>/errorpage.jsp</error>
 <message key=”error.read”>没有权限读取的信息</message>
</mapping>
<mapping name=”add” url=”/add.do”>
 <error>/errorpage.jsp</error>
 <message key=”error.add”>没有权限添加的信息</message>
</mapping>
<mapping name=”delete” url=”/delete.do”>
 <error>/errorpage.jsp</error>
 <message key=”error.delete”>没有权限删除的信息</message>
</mapping>

用户的权限最终表示成一个二进制数,当用户访问一个URL是,如果第i个mapping匹配了这个URL,就检查用户权限二进制数的第i位,如果该位为1说明用户有此权限,为0则说明用户无此权限。

OK,那么怎么设定用户权限呢?总不能随便给一串二进制数吧!当然不能。下面是两个设定用户权限的方法:
 
一:用户权限用二进制数表示,在负责权限管理的类中(所有的一切和validation一样,应该是有一个类库的)有getCode(mapping- name)方法,getCode返回一个n位二进制串,如果名字为mapping-name的mapping在第i位,则此二进制数的第i位为1,其他位 为0。如果用户设定的权限有read和add,使用getCode(“read”)和getCode(“add”)获得两串权限码,再进行按位或运算就得 到用户的最终权限码,用上面的设置,getCode(“read”)返回”100”,getCode(“add”)返回”010”,用户的权限码就是 100|010=110,也就是读和添加权限。
 
二:用户权限用十进制数表示,经常用linux的朋友可能更喜欢这种方式,因为大家都喜欢用”chmod 744 文件名”的方式设定文件权限。这种方式中,负责权限管理的类返回的是一个10进制数,这个十进数的值和上面说的二进制数的值是相等的,比如二进制返回 100,十进制就是4(二进制转十进制嘛!)。和上面相似,这次不是按位或运算,而是直接加运算。

还是设置读和添加权限,getCode(“read”)返回4,getCode(“add”)返回2,用户权限的表示就是2+4=6.

上面是总体方案,在具体实现时,用一个长整型数表示权限。还设计了一个接口:

Java代码 
1.Privilege{  
2.        public long getPrivilege()  
3.}//User对象应该实现这个接口,这样在Filter中我们使用  
4.Privilege p=(Privilege)session.getAttribute("user");  
5.p.getPrivilege(); 

Privilege{
  public long getPrivilege()
}//User对象应该实现这个接口,这样在Filter中我们使用
Privilege p=(Privilege)session.getAttribute("user");
p.getPrivilege();就可以获取权限码。
其他细节还有url可以使用正则表达式,如果用户请求的url匹配多个配置项,那么只有用户的权限匹配所有的要求时才能算通过。这也安全性好一点。对没有配置的url,默认全部不需要任何权限,即任何人可访问。

在前台,我们一般都不会显示不想用户看到的超链接。比如对一个只有发布新闻的用户,肯定不想他看到删除新闻的链接。我的方案是在设计一个标签<privilege>有url属性,表示下面的操作要访问的url。如删除新闻:

Java代码 
1.<privilege url="/deletenews.do">other</privilege> 
<privilege url="/deletenews.do">other</privilege>
标签的大致实现是:获取当前用户权限码,获取配置文件中url的权限码。如果当前用户的权限不足以访问该url,则skipbody,否则eavlbody。(可以省去一堆if)。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。