﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Gnome's Blog-文章分类-技术专题</title><link>http://www.blogjava.net/weakfi/category/37178.html</link><description>绚烂是我，平淡也是我</description><language>zh-cn</language><lastBuildDate>Wed, 07 Jan 2009 17:42:51 GMT</lastBuildDate><pubDate>Wed, 07 Jan 2009 17:42:51 GMT</pubDate><ttl>60</ttl><item><title>基于URL的权限控制</title><link>http://www.blogjava.net/weakfi/articles/250427.html</link><dc:creator>李聪平</dc:creator><author>李聪平</author><pubDate>Wed, 07 Jan 2009 16:24:00 GMT</pubDate><guid>http://www.blogjava.net/weakfi/articles/250427.html</guid><wfw:comment>http://www.blogjava.net/weakfi/comments/250427.html</wfw:comment><comments>http://www.blogjava.net/weakfi/articles/250427.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weakfi/comments/commentRss/250427.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weakfi/services/trackbacks/250427.html</trackback:ping><description><![CDATA[<base /><style> body {padding:0;margin:0;}</style>
<link href="/css/cuteeditor.css" rel="stylesheet" />&nbsp;
<h2 style="text-align: center;" align="center"><span style="font-family: 黑体;">基于</span>URL<span style="font-family: 黑体;">的权限控制</span></h2>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体;">最近一直在做毕业设计的后台管理模块。很早以前就想写一篇关于权限控制的文章，苦于一直不理解如何用</span>URL<span style="font-family: 宋体;">实现。以至于当初设计数据库和编写页面实现的时候都没有将权限的</span>URL<span style="font-family: 宋体;">考虑进去，当时只想直接匹配权限的名称就可以了。直到前几天在</span>JavaEye<span style="font-family: 宋体;">论坛上看到了一篇题为《</span><a href="http://www.javaeye.com/topic/300513"><span style="font-family: 宋体;">一个简易实用的web<span style="font-family: 宋体;">权限管理模块的应用与实现</span></span></a><span style="font-family: 宋体;">》的文章才对基于</span>URL<span style="font-family: 宋体;">的权限控制有了较深的认识。加上之前一直在用另一种方法来实现相同功能，所以这几天一直在总结这两种方法的优劣之处。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体;">值得提醒的是，本文只关注基于</span>URL<span style="font-family: 宋体;">和不基于</span>URL<span style="font-family: 宋体;">两种方法的优劣之处和具体如何实现。数据库设计不会讲的很详细，虽然那也是很重要的，但是关于它的好坏很难有一个统一的标准，这个要看系统具体实现的功能和对效率的要求如何。其实即使是教科书上面提到的规范在实际应用中也是起到参考作用而已，很多时候我们宁愿牺牲规范来换取效率。总之一句话：简单才是美。如果想深入去研究数据库该如何设计的话建议去看看上面提到的文章中的回复，里面大量回复都是针对数据库设计的。好了，先引用上述文章的一些重点内容先：</span></p>
<p>&nbsp;&gt;&gt;&nbsp; 引用开始</p>
<p><span style="color: blue; font-family: 宋体;">本文介绍一个简易实用的</span><span style="color: blue;">web</span><span style="color: blue; font-family: 宋体;">权限管理模块的应用与实现。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">先介绍数据模型和应用界面，后继对实现细节做选择性阐述。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">数据表关系如下：</span></p>
<p><span style="color: blue;">&nbsp;&nbsp; <img alt="" src="http://www.javaeye.com/upload/picture/pic/28217/d47d27ba-155e-33fe-8e55-549aa76ff25b.png" width="580" border="0" height="362" /></span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">该图标明了登陆用户、角色、部门（机构）、用户组、角色和模块功能之间的关系。为方便起见，所有表都只保留必要字段。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">在本系统设计中，如下概念有着相对特殊的含义。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">一、用户</span><span style="color: blue;">(user)</span><span style="color: blue; font-family: 宋体;">：</span><span style="color: blue; font-family: 宋体;">系统的使用者。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">二、部门</span><span style="color: blue;">(org)</span><span style="color: blue; font-family: 宋体;">：体现了用户的行政关系，</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">三、组</span><span style="color: blue;">(group)
</span><span style="color: blue; font-family: 宋体;">：是某相同职能的用户的集合，可以和用户一样与角色产生关联。设置组的目的是为了方便用户的角色分配，减少用户与角色的直接对应关系。用户的角色可以是其</span><span style="color: blue; font-family: 宋体;">组角色和其直接分配的角色之合集。限于作者的时间和精力，组功能在该系统中没有具体的实现。</span><span style="color: blue;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">四、角色</span><span style="color: blue;">(role)</span><span style="color: blue; font-family: 宋体;">：角色对应着某些功能</span><span style="color: blue;">(function)</span><span style="color: blue; font-family: 宋体;">的集合，被分配一个角色意味着有权执行这些功能。角色表中的字段</span><span style="color: blue;">"functions"</span><span style="color: blue; font-family: 宋体;">记录相关的功能</span><span style="color: blue;">id,id</span><span style="color: blue; font-family: 宋体;">之间用逗号隔开。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">五、功能</span><span style="color: blue;">(function)</span><span style="color: blue; font-family: 宋体;">：系统的一个或者多个执行准入。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">那么如何表现</span><span style="color: blue;">&#8220;</span><span style="color: blue; font-family: 宋体;">功能</span><span style="color: blue;">&#8221;</span><span style="color: blue; font-family: 宋体;">以最终实现控制用户的每一个细微动作呢？假如不特定于某种架构，可以这么设计该表字段：</span></p>
<p><span style="color: blue;">Sql</span><span style="color: blue; font-family: 宋体;">代码</span><span style="color: blue; font-family: 宋体;">：省略。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">假定有三个</span><span style="color: blue;">web</span><span style="color: blue; font-family: 宋体;">访问路径</span><span style="color: blue;"> <br />
&nbsp;
<a href="http://127.0.0.1:8080/app/sys/user.jsp?action=index&amp;userid=1203">http://127.0.0.1:8080/app/sys/user.jsp?action=index&amp;userid=1203</a>&nbsp;
<br />
&nbsp;&nbsp;<a href="http://127.0.0.1:8080/app/sys/user.yuetong?action=add">http://127.0.0.1:8080/app/sys/user.yuetong?action=add</a><br />
&nbsp;&nbsp;<a href="http://127.0.0.1:8080/app/sys/user.yuetong?action=update&amp;userid=1203">http://127.0.0.1:8080/app/sys/user.yuetong?action=update&amp;userid=1203</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;
</span><span style="color: blue; font-family: 宋体;">这三个访问点被人为的划分为两个功能准入（当然亦可以是一个或者三个），见下图</span><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="color: blue;">&nbsp;&nbsp;<img alt="" src="http://www.javaeye.com/upload/picture/pic/28251/e716dc99-599e-3c30-ae69-e6ab211db836.bmp" width="588" border="0" height="89" />&nbsp;
</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">由此可知，</span><span style="color: blue;">&#8220;</span><span style="color: blue; font-family: 宋体;">功能</span><span style="color: blue;">&#8221;</span><span style="color: blue; font-family: 宋体;">是衡量用户准入的最小刻度。在用户访问某个地址的时候，我们可以通过解析</span><span style="color: blue;">URL</span><span style="color: blue; font-family: 宋体;">对比他拥有的</span><span style="color: blue;">&#8220;</span><span style="color: blue; font-family: 宋体;">功能</span><span style="color: blue;">&#8221;</span><span style="color: blue; font-family: 宋体;">权限来实现权限管理。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">借助于某些架构或者设计思路，可以避免用户直接访问</span><span style="color: blue;">JSP</span><span style="color: blue; font-family: 宋体;">页面，甚至全系统的访问地址都使用同一后缀，这种情况下可以省去</span><span style="color: blue;">SUFFIX</span><span style="color: blue; font-family: 宋体;">字段。　本系统就是这种情况（</span><span style="color: blue;">JSP</span><span style="color: blue; font-family: 宋体;">页面置于</span><span style="color: blue;">WEB-INF</span><span style="color: blue; font-family: 宋体;">下，采用</span><span style="color: blue;">struts2</span><span style="color: blue; font-family: 宋体;">架构）。</span></p>
<p><span style="color: blue;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue; font-family: 宋体;">六、功能模块树（</span><span style="color: blue;">function tree</span><span style="color: blue; font-family: 宋体;">）：功能的目录组织，起分类的作用。在为角色设定功能的时候，用户界面可以利用带选择框的</span><span style="color: blue;">js</span><span style="color: blue; font-family: 宋体;">树。而这颗</span><span style="color: blue;">js</span><span style="color: blue; font-family: 宋体;">树是后台的功能树表以及功能表的联合</span><span style="color: blue; font-family: 宋体;">表现形式。功能模块树可以方便的与菜单树建立映射关系，限于作者的时间和精力，该系统并未实现菜单树。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体;">作者对权限控制这一块估计也是比较有经验了，考虑的东西挺全面的。从他的数据库设计中可以看出真正核心的表只有两个：角色和权限。当然实际开发时一般不太可能设计的这么简单，其他表的作用就是用来优化你的数据模型和方便以后扩展用的。你的数据库设计的灵不灵活、健不健壮、安不安全就看其他表如何设计了。本着简单就是美的原则，我设计的数据库有四个表：</span></p>
<p><span style="font-family: 宋体;">用户信息：保存用户的基本信息，</span>rolid<span style="font-family: 宋体;">与角色组的</span>ID<span style="font-family: 宋体;">关联</span></p>
<p><span style="font-family: 宋体;">角色组：方便用户管理，用户通过角色组和权限发生关联</span></p>
<p><span style="font-family: 宋体;">角色权限：</span>rolid<span style="font-family: 宋体;">和</span>fctid<span style="font-family: 宋体;">分别和角色组</span>ID<span style="font-family: 宋体;">，功能列表</span>ID<span style="font-family: 宋体;">发生关联。</span>have<span style="font-family: 宋体;">字段的数据类型为</span>Boolean<span style="font-family: 宋体;">，表示</span>ID<span style="font-family: 宋体;">为</span>rolid<span style="font-family: 宋体;">的角色组是否具有</span>ID<span style="font-family: 宋体;">为</span>fctid<span style="font-family: 宋体;">的权限</span></p>
<p><span style="font-family: 宋体;">功能列表：系统的一个或者多个执行准入。由于系统使用了</span>Struts2<span style="font-family: 宋体;">，所以后缀名统一为</span>action<span style="font-family: 宋体;">，省略了</span>suffix<span style="font-family: 宋体;">字段。</span>Module<span style="font-family: 宋体;">是为了以后功能增多，需要分模块的时候预留的，目前没有实现。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体;">除去那些組的概念，这个设计和上文作者的最大不同就是角色组和权限发生关联的方式，他是用角色组里面的一个字段</span>functions<span style="font-family: 宋体;">保存权限</span>ID<span style="font-family: 宋体;">，</span>id<span style="font-family: 宋体;">之间用逗号隔开。我的想法比较简单，既然角色组和权限列表之间是多对多的关系，那就在它们之间新建一个连接表。比较麻烦的就是他们之间的级联关系，如果你没有用</span>Hibernate<span style="font-family: 宋体;">或</span>EJB<span style="font-family: 宋体;">来帮你实现这些级联操作又不想在数据库里面使用外键，那么在用代码操作数据库的时候就要格外留心了，通常我都不能一次就把那些级联关系用代码完整的实现，每次都等到出错了再去找原因。所以动手写代码前还是考虑周全点好。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OK<span style="font-family: 宋体;">，到具体实现了。<strong>第一种方法，假设我不用</strong></span><strong>URL<span style="font-family: 宋体;">，那么新建权限的时候只需填写权限的名称和描述，很简单。</span></strong></p>
<p style="text-align: center;" align="center"><img alt="" src="http://www.blogjava.net/images/blogjava_net/weakfi/37177/r_2.bmp" width="415" border="0" height="248" /></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体;">假设我新增了一个叫&#8220;管理用户组&#8221;的权限，那么我首先需要在用户登录成功后保存他的角色组</span>ID<span style="font-family: 宋体;">到</span>Session<span style="font-family: 宋体;">里面，然后在对应的</span>Action<span style="font-family: 宋体;">类的开头添加这些代码：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">Integer rolid
= (Integer) ActionContext.<em>getContext</em>().getSession().get(</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"rolid"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">);&nbsp;&nbsp; //
</span><span style="font-size: 10pt; color: black; font-family: 宋体;">获取角色组</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">ID</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">if</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';">
(manager.getRight(rolid, </span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: #2a00ff; font-family: 宋体;">用户组管理</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">))
{</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //
do something</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">return</span></strong><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"grouplist"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">;</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">else</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';"> {</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">if</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';">
(manager.getMSG().equals(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"unallocate"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">))
{</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">this</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';">.setMsg(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: #2a00ff; font-family: 宋体;">对不起，该权限尚未分配！</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">);</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">else</span></strong><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">if</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';">(manager.getMSG().equals(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"error"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">))
{</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">this</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';">.setMsg(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: #2a00ff; font-family: 宋体;">系统出错！</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">);</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">else</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';"> {</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">this</span></strong><span style="font-size: 10pt; color: black; font-family: 'Courier New';">.setMsg(</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: #2a00ff; font-family: 宋体;">对不起，你无权查看用户组信息！</span><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">);</span></p>
<p><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</span></p>
<p><span style="font-size: 10pt; color: black; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: 'Courier New';">return</span></strong><span style="font-size: 10pt; color: #2a00ff; font-family: 'Courier New';">"error"</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">;</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">}</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">manager</span><span style="font-size: 10pt; color: black; font-family: 宋体;">是</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">Manager</span><span style="font-size: 10pt; color: black; font-family: 宋体;">类的一个实例，</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">
getRight()</span><span style="font-size: 10pt; color: black; font-family: 宋体;">方法实现查询角色组是否具有某项权限的功能。需要传入角色组</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">ID</span><span style="font-size: 10pt; color: black; font-family: 宋体;">和权限名称参数。如果查询不到权限名称为&#8220;用户组管理&#8221;的权限则说明该权限还没有分配。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><span style="font-size: 10pt; color: black; font-family: 宋体;">这样做的缺点很明显：</span></p>
<p style="margin-left: 75pt; text-indent: -33pt;"><span style="font-size: 10pt; color: black; font-family: 'Courier New';">1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;</span></span><span style="font-size: 10pt; color: black; font-family: 宋体;">造成代码冗余。假如我的用户组管理又分为显示、新增、修改和删除的功能，那么我需要在每个方法的开头都加上这些代码。那么当权限变多了，就要不断的重复这些代码，重用性低也很不利于以后的维护。</span></p>
<p style="margin-left: 75pt; text-indent: -33pt;">2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt; color: black; font-family: 宋体;">灵活性差。如果我需要对某项权限的名称进行修改，那么只能在后台先把原来的权限删除掉，然后再新建一个和代码里面的名称相同的匹配起来。又或者是直接到代码里面的修改，改完还有重新部署，太麻烦了。</span></p>
<p style="margin-left: 75pt; text-indent: -33pt;">3.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt; color: black; font-family: 宋体;">效率低。每次执行判断都需要去数据库执行一次而查询，还是多表连接查询。</span></p>
<p style="margin-left: 75pt; text-indent: -33pt;">4.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt; color: black; font-family: 宋体;">暂时想不到</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><span style="font-size: 10pt; color: black; font-family: 宋体;">造成这些缺点的原因就是在代码里面直接使用到了数据库里面保存的信息。数据库里面的数据是会经常改变的，而代码在项目完成后是不能再改的。不然就叫做升级或者是你系统有漏洞了。所以需要在代码和权限信息之间引入一种相对不变的&#8220;变量&#8220;，然后让代码和那个&#8220;变量&#8220;发生关联，而数据库里面只需添加几个字段。那个&#8220;变量&#8221;就是</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">URL</span><span style="font-size: 10pt; color: black; font-family: 宋体;">，相信很少人会在</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">web.xml</span><span style="font-size: 10pt; color: black; font-family: 宋体;">或</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">struts.xml</span><span style="font-size: 10pt; color: black; font-family: 宋体;">里面部署完</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">URL</span><span style="font-size: 10pt; color: black; font-family: 宋体;">后还会去改它。不过即使修改也没关系，容器会自动帮你重新部署，问题不大。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><strong><span style="font-size: 10pt; color: black; font-family: 宋体;">第二种方法：使用</span><span style="font-size: 10pt; color: black; font-family: 'Courier New';">URL</span><span style="font-size: 10pt; color: black; font-family: 宋体;">。那么新建权限的时候就要填写多两个信息。</span></strong></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><img alt="" src="http://www.blogjava.net/images/blogjava_net/weakfi/37177/r_1.bmp" width="445" border="0" height="346" /></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><span style="font-family: 宋体;">同样新增一个叫做&#8220;管理用户组&#8221;的权限，</span>url<span style="font-family: 宋体;">为</span>/sys/group<span style="font-family: 宋体;">，</span>params<span style="font-family: 宋体;">为</span>list<span style="font-family: 宋体;">。</span></p>
<p style="margin-left: 21pt; text-indent: 21pt;"><span style="font-family: 宋体;">那么同样在登录成功后需要保存用户的角色组</span>ID<span style="font-family: 宋体;">，然后实现一个方法去根据角色组</span>ID<span style="font-family: 宋体;">来查询该角色组拥有的所有权限的</span>URL<span style="font-family: 宋体;">，然后再用</span>request.getRequestURL()<span style="font-family: 宋体;">来获得当前</span>URL<span style="font-family: 宋体;">和用户具有的</span>URL<span style="font-family: 宋体;">进行匹配。这样做确实变得灵活了，你可以在管理后台尽情修改权限信息，包括名称和</span>URL<span style="font-family: 宋体;">，只要和你在部署文件中编写的</span>URL<span style="font-family: 宋体;">保持一致就可以了。但是依然存在代码冗余和效率差的缺点。下面是我的改进方法：</span></p>
<p style="margin-left: 60pt; text-indent: -18pt;">1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">设计一个</span>PowerInfo<span style="font-family: 宋体;">类用来保存用户的权限信息，当用户登录成功后，新建一个对象把查询数据库返回的信息保存在里面，然后再把对象添加到</span>Session<span style="font-family: 宋体;">。以后需要进行权限判断的时候都从</span>Session<span style="font-family: 宋体;">里面取出该对象进行</span>URL<span style="font-family: 宋体;">匹配。这样就解决了效率低的问题。</span></p>
<p style="margin-left: 63pt;">public class PowerInfo {</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // <span style="font-family: 宋体;">可访问资源</span></p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private ArrayList&lt;String&gt; uri;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private ArrayList&lt;String&gt; params;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // <span style="font-family: 宋体;">记录用户的越权次数，当次数超过规定的时候自动退出系统</span></p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int ultravires;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public ArrayList&lt;String&gt; getUri()
{</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return uri;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setUri(ArrayList&lt;String&gt;
uri) {</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.uri = uri;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public ArrayList&lt;String&gt; getParams()
{</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return params;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void
setParams(ArrayList&lt;String&gt; params) {</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.params = params;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int getUltravires() {</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ultravires;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setUltravires(int ultravires)
{</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ultravires = ultravires;</p>
<p style="margin-left: 63pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="margin-left: 63pt;">}</p>
<p style="margin-left: 60pt; text-indent: -18pt;">2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">使用</span>Filter<span style="font-family: 宋体;">过滤所有的用户请求，在</span>Filter<span style="font-family: 宋体;">里面用当前</span>URL<span style="font-family: 宋体;">和用户权限的</span>URL<span style="font-family: 宋体;">进行匹配。这样就解决了代码冗余的问题。实现这个方法的时候有个问题需要注意，当我使用了</span>Struts2<span style="font-family: 宋体;">后，发现凡是</span>.action<span style="font-family: 宋体;">后缀的请求都不经过我的</span>Filter<span style="font-family: 宋体;">。只是</span>.jsp<span style="font-family: 宋体;">的才会过滤。这个问题具体为什么我也不是很清楚，但和你部署</span>Filter<span style="font-family: 宋体;">的位置肯定有关，因为当我把自己写的</span>Filter<span style="font-family: 宋体;">部署到</span>struts2<span style="font-family: 宋体;">的</span>Filter<span style="font-family: 宋体;">前面的时候问题就解决了。估计如果</span>struts2<span style="font-family: 宋体;">的</span>Filter<span style="font-family: 宋体;">先在前面处理了</span>.action<span style="font-family: 宋体;">的请求后不执行</span>chain.doFilter(request,response)<span style="font-family: 宋体;">就直接返回界面给用户了。</span></p>
<p style="margin-left: 21pt; color: #003366;"><span style="font-family: 宋体;">&nbsp;&nbsp;&nbsp;&nbsp;以上是本人对基于</span>URL<span style="font-family: 宋体;">实现权限控制的一些不成熟想法。欢迎各位指出不足之处。</span></p>
<img src ="http://www.blogjava.net/weakfi/aggbug/250427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weakfi/" target="_blank">李聪平</a> 2009-01-08 00:24 <a href="http://www.blogjava.net/weakfi/articles/250427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>