﻿<?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-Terry.B.Li           彬-文章分类-Spring Security</title><link>http://www.blogjava.net/libin2722/category/46078.html</link><description>虚其心，可解天下之问；专其心，可治天下之学；静其心，可悟天下之理；恒其心，可成天下之业。</description><language>zh-cn</language><lastBuildDate>Thu, 16 Sep 2010 09:52:05 GMT</lastBuildDate><pubDate>Thu, 16 Sep 2010 09:52:05 GMT</pubDate><ttl>60</ttl><item><title>权限控制：spring 3.0 security配置例子</title><link>http://www.blogjava.net/libin2722/articles/332006.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Tue, 14 Sep 2010 10:51:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/332006.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/332006.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/332006.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/332006.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/332006.html</trackback:ping><description><![CDATA[
		<p>以最新版的spring-security-3.0.2作为介绍对象，如果你了解Spring 2.0 
Security的话，那就比较抱歉了，因为spring-security-3.0.2与2.0相比改动很大，在2.0中的一些配置拿到3.0几乎是行
不通的，如果你还没有接触过spring，那么以下是其地址：</p>
		<p>Spring官方网址：<a href="http://www.springsource.org/">http://www.springsource.org/</a></p>
		<p>spring-security下载地址：</p>
		<p>
				<a href="http://static.springsource.org/spring-security/site/downloads.html">http://static.springsource.org/spring-security/site/downloads.html</a>
		</p>
		<p>我以其自带的一个简单例子来介绍一下吧，因为这个例子配置不对的话极易报错（这个例子是个打包的War文件，但与文档中的又不一样，所以极易出错），我会对出现的错误给予出错原因及解决方法。</p>
		<p>
				<span id="more-2081">
				</span>首先通过spring-security地址下载到最新版的spring-security-3.0.2.RELEASE.zip，然后解压开来，在解压开的目录dist中，你会看到如下一些文件：</p>
		<p>
				<a href="http://www.zihou.me/uploads/2010/04/11.png">
						<img class="size-full wp-image-2082 alignnone" title="1" src="http://www.zihou.me/uploads/2010/04/11.png" alt="" height="480" width="447" />
				</a>
		</p>
		<p>看到spring-security-samples-tutorial-3.0.2.RELEASE.war了吗？我就以这个为例，把这个包拷贝
到你Web服务器（如Tomcat）的webapps目录下，启动服务器后，会生成一个spring-security-samples-
tutorial-3.0.2.RELEASE项目，可以把名字改短一点方便访问，比如我这里改名为：spring-security，这样通过<a href="http://127.0.0.1/spring-security">http://127.0.0.1/spring-security</a>可以直接访问了。</p>
		<p>
				<a href="http://www.zihou.me/uploads/2010/04/21.png">
						<img class="size-full wp-image-2083 alignnone" title="2" src="http://www.zihou.me/uploads/2010/04/21.png" alt="" height="199" width="326" />
				</a>
		</p>
		<p>进入目录WEB-INF，可以看到如上的一些文件，其中，applicationContext-security.xml是权限控制配置文件，所
有的权限控制都是在其中配置的，bank-servlet.xml是系统的上下文配置文件，可以在其中配置访问路径映射（类似于Struts-1.x中的
struts-config.xml或struts-2.x中的struts.xml文件），也可以在其中进行一些装配等工作，属于spring级的，与
安全配置没多大关系。</p>
		<p>具体的文件内容我就不展示了，因为可以自己打开看，我这里只说要注意的一些地方：</p>
		<p>
				<strong>1、在web.xml中的配置</strong>
		</p>
		<p>服务启动时加载applicationContext-security.xml文件：</p>
		<pre>&lt;context-param&gt;

&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;

&lt;param-value&gt;

/WEB-INF/applicationContext-security.xml

&lt;/param-value&gt;

&lt;/context-param&gt;
</pre>
		<p>要过滤链接的形式</p>
		<p>&lt;filter&gt;</p>
		<p>&lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;</p>
		<p>&lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;/filter-class&gt;</p>
		<p>&lt;/filter&gt;</p>
		<p>&lt;filter-mapping&gt;</p>
		<p>&lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;</p>
		<p>&lt;url-pattern&gt;/*&lt;/url-pattern&gt;</p>
		<p>&lt;/filter-mapping&gt;</p>
		<p>你一定注意到了，这里的filter-class与Spring2.0的不同之处，如果你了解Spring2.0的话，的确，在Spring2.0中为：</p>
		<p>&lt;filter-name&gt;acegiFilterChain&lt;/filter-name&gt;</p>
		<p>&lt;filter-class&gt;org.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;</p>
		<p>这就是3.0与2.0改变很大的一个地方，2.0用的为Acegi，后来Acegi嵌入到了Spring中，成为了Spring Security，所以包的路径也都改变了！</p>
		<p>
				<strong>2、在applicationContext-security.xml中的配置</strong>
		</p>
		<pre>
				<strong>&lt;http use-expressions="true"&gt;</strong>

&lt;intercept-url pattern="/secure/extreme/**" access="hasRole('ROLE_SUPERVISOR')"/&gt;

&lt;intercept-url pattern="/secure/**" access="isAuthenticated()" /&gt;

&lt;!-- Disable web URI authorization, as we're using &lt;global-method-security&gt; and have @Secured the services layer instead

&lt;intercept-url pattern="/listAccounts.html" access="isRememberMe()" /&gt;

&lt;intercept-url pattern="/post.html" access="hasRole('ROLE_TELLER')" /&gt;

--&gt;

&lt;intercept-url pattern="/**" access="permitAll" /&gt;

&lt;form-login /&gt;

&lt;logout /&gt;

&lt;remember-me /&gt;

&lt;!--

Uncomment to enable X509 client authentication support

&lt;x509 /&gt;

--&gt;

&lt;!-- Uncomment to limit the number of sessions a user can have --&gt;

&lt;session-management invalid-session-url="/timeout.jsp"&gt;

&lt;concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /&gt;

&lt;/session-management&gt;

&lt;/http&gt;
</pre>
		<p>
				<strong>上面这段是初用者比较容易出错的地方</strong>，这其实也是写这篇文章的主要原因之一，注意到第一行的黑体字：</p>
		<p>
				<strong>&lt;http use-expressions=”true”&gt;</strong>
		</p>
		<p>表示这里的配置可以使用一种表达式，这种表达式就是类似于isAuthenticated()这样的写法，在后面会看到与这种写法不一样但同样可以达到相同效果的写法。</p>
		<p>intercept-url表示要拦截的url形式，比如</p>
		<p>&lt;intercept-url pattern=”/secure/**” access=”isAuthenticated()” /&gt;</p>
		<p>表示根目录下的secure目录需要经过验证后才能访问的。</p>
		<p>&lt;form-login /&gt;是Spring 
Security自动为你生成的一个简陋的登录页面，即使你没有创建任何登录页面，当然你也可以修改，但不建议你修改，因为你可以不使用默认的，可以采用
如下方式：&lt;form-login login-page=’/ login.html’/&gt;自定义一个登录页面。</p>
		<p>其他的说明可以参考一个翻译的中文文档：</p>
		<p>
				<a href="http://www.family168.com/tutorial/springsecurity3/html/ns-config.html" target="_blank">http://www.family168.com/tutorial/springsecurity3/html/ns-config.html</a>
		</p>
		<p>
				<strong>3、容易出错的地方</strong>
		</p>
		<p>在上面的翻译文档（也是翻译自官方文档）或英文官方文档中，给出的与上面例子功能相似的说明大概是这样的：</p>
		<pre>  <strong>&lt;http auto-config='true'&gt;</strong></pre>
		<pre>    &lt;intercept-url pattern="/**" access="ROLE_USER" /&gt;</pre>
		<pre>  &lt;/http&gt;</pre>
		<p>注意到与上面例子不同的地方了吗？</p>
		<p>还是注意第一行，这回不是<strong>&lt;http use-expressions=”true”&gt;</strong>而是<strong>&lt;http auto-config=’true’&gt;</strong>了，而下面的配置</p>
		<p>&lt;intercept-url pattern=”/**” <strong>access=”ROLE_USER”</strong> /&gt;也与上面的写法不同，事实上如果是<strong>&lt;http use-expressions=”true”&gt;</strong>的话，这句<strong>access=”ROLE_USER”</strong>就是错的，正确的写法就应该为：hasRole(‘ROLE_USER’)。</p>
		<p>这不得不说这是Spring Security的文档与例子不搭配的一个低级错误，因为当一个使用者在打开例子又看到文档说明时，他往往不知道这两者有何区别，就如同我刚使用的时候一样，我在使用<strong>&lt;http use-expressions=”true”&gt;</strong>的同时，将<strong>access=”ROLE_USER”</strong>这种写法也写了进来，结果可想而知，报了错！报错信息诸如：</p>
		<pre>org.apache.jasper.JasperException: java.lang.IllegalArgumentException: Failed to evaluate
expression 'ROLE_SUPERVISOR'</pre>
		<p>就是说<strong>use-expressions</strong>这种表示法是不认识<strong>access=”ROLE_USER”</strong>这种写法的，另外，当使用了<strong>&lt;http use-expressions=”true”&gt;</strong>时，一定要在配置中至少有一个符合<strong>use-expressions</strong>的表示法，否则就会报类似如下错误：</p>
		<pre>org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property
'ROLE_SUPERVISOR' cannot be found on object of type 'org.springframework.security.web.access.
expression.WebSecurityExpressionRoot'</pre>
		<p>这个简单的配置例子大概就写这么多吧，最后说说我对Spring Security的看法，我个人觉得Spring 
Security的功能的确是很强大，考虑得也非常全面，几乎什么都想替使用者做完，但正是它的这点，我觉得倒是它的缺点，在我了解它并配置的过程中，我
个人觉得是非常复杂繁琐的，而且它现在的文档支持也并不好，正如上面所看到的一样，文档与例子中的写法都不一致。事实上，使用者并不希望它什么都做到，比
如它做的那个缺省登录页面，那个有意义吗？使用者比如我，其实就是希望一个很简单的权限判断，比如我打开某一个链接，然后你告诉我访问者有无权限访问，给
我返回一个类似true或false的结果就够了！至于其他的事情，我是如何的处理后续过程并不用Spring 
Security操心的，但很显然，子猴认为Spring Security在这点上做得并不好。
</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/332006.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-14 18:51 <a href="http://www.blogjava.net/libin2722/articles/332006.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>域对象的安全(Domain Object Security)</title><link>http://www.blogjava.net/libin2722/articles/329982.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Thu, 26 Aug 2010 08:01:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/329982.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/329982.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/329982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/329982.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/329982.html</trackback:ping><description><![CDATA[
		<h2>24.1. <span style="font-family: 黑体;">概述</span></h2>
		<p>
				<strong>请注意：</strong>在<span style="font-family: Arial;">2.0.0</span>之前，<span style="font-family: Arial;">Spring Security</span>称为<span style="font-family: Arial;">Acegi
Security</span>。老的<span style="font-family: Arial;">Acegi Security</span>提供了一个<span style="font-family: Arial;">ACL</span>模块，放在<code><span style="font-family: Arial;">org.[acegisecurity/springsecurity].acl</span></code><code>包下。这个老的现在已经被抛弃，并可能会在将来的</code><code><span style="font-family: Arial;">Spring Security</span></code><code>发行版中去掉。本章讨论新的</code><code><span style="font-family: Arial;">ACL</span></code><code>模块，官方推荐在</code><span style="font-family: Arial;">Spring Security 2.0.0</span>或更高版本中使用，它被置于<code><span style="font-family: Arial;">org.springframework.security.acls</span></code><code>包下。</code></p>
		<p>复杂的应用常常会有需要定义访问权限——不只是在<span style="font-family: Arial;">web</span>请求和方法调用水平的控制。而是安全决议需要由“<span style="font-family: Arial;">who (<code><span style="font-family: Arial;">Authentication</span></code>), where (<code><span style="font-family: Arial;">MethodInvocation</span></code>) and what (<code><span style="font-family: Arial;">SomeDomainObject</span></code>)</span>”构成。也就是说，授权决议还要考虑方法调用中的实际域对象。</p>
		<p>想象你正在为宠物诊所设计一个应用。你的基于<span style="font-family: Arial;">Spring</span>的应用主要有两组用户：宠物诊所的职员和客户。职员可以访问所有数据，但客户只能看到自己的客户记录。为了使这个例子更加有趣一点，你的客户可以让其它客户看他们的客户记录，例如他们<span style="font-family: Arial;">"puppy
preschool"</span>的顾问或本地<span style="font-family: Arial;">"Pony Club"</span>的总裁。以<span style="font-family: Arial;">Spring Security</span>为基础，你有几个方式可以选择：</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-family: Arial;">
						<span>1.<span style="font: 7pt &quot;Times New Roman&quot;;">     
</span></span>
				</span>编写一个自己的业务方法强制安全控制。你可以从<span style="font-family: Arial;">Customer</span>域对象中获取一个有访问权限用户的集合。可以用<code><span style="font-family: Arial;">SecurityContextHolder.getContext().getAuthentication()</span></code><code>来访问</code><code><span style="font-family: Arial;">Authentication</span></code><code>对象。</code></p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-family: Arial;">
						<span>2.<span style="font: 7pt &quot;Times New Roman&quot;;">     
</span></span>
				</span>
				<code>编写一个</code>
				<code>
						<span style="font-family: Arial;">AccessDecisionVoter</span>
				</code>
				<code>，通过</code>
				<code>
						<span style="font-family: Arial;">Authentication</span>
				</code>
				<code>中储存的</code>
				<code>
						<span style="font-family: Arial;">GrantedAuthority[]</span>
				</code>
				<code>来控制安全检查。这意味着你的</code>
				<code>
						<span style="font-family: Arial;">AuthenticationManager</span>
				</code>
				<code>要把代表用户对域对象访问权限的</code>
				<code>
						<span style="font-family: Arial;">GrantedAuthority</span>
				</code>
				<span style="font-family: Arial;">[]</span>填充到<code><span style="font-family: Arial;">Authentication</span></code><code>对象中去。</code></p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-family: Arial;">
						<span>3.<span style="font: 7pt &quot;Times New Roman&quot;;">     
</span></span>
				</span>编写一个<code><span style="font-family: Arial;">AccessDecisionVoter</span></code><code>来强制安全控制，直接打开目标</code><code><span style="font-family: Arial;">Customer</span></code><code>域对象。这意味着你的</code><code><span style="font-family: Arial;">voter</span></code><code>需要访问</code><code><span style="font-family: Arial;">DAO</span></code><code>来获取</code><code><span style="font-family: Arial;">Customer</span></code><code>对象。它接着会访问</code><code><span style="font-family: Arial;">Customer</span></code><code>对象集合来进行安全决议。</code></p>
		<p>这些方法都是合情合理的。但是，第一个方法把你的授权检查和业务代码耦合到一起了。带来的主要问题包括提高了单元测试的难度，以及<code><span style="font-family: Arial;">Customer</span></code><code>授权逻辑很难在其它地方重用。从</code><code><span style="font-family: Arial;">Authentication</span></code>中获取<code><span style="font-family: Arial;">GrantedAuthority[]</span></code><code>是好的，但是面对数量很大的</code><code><span style="font-family: Arial;">Customer</span></code><span style="font-family: Arial;">s</span>时也是不行的。如果用户访问的<code><span style="font-family: Arial;">Customer</span></code><span style="font-family: Arial;">s</span>数量可能达到<span style="font-family: Arial;">5,000</span>个（在这个例子里不大可能，但是想象如果是一个很大的<span style="font-family: Arial;">Pony Club</span>里的兽医！），构建<code><span style="font-family: Arial;">Authentication</span></code><code>需要耗费的内存和时间可能不是你想要的。最后一种方法，编写代码从外部直接打开</code><code><span style="font-family: Arial;">Customer</span></code><code>，可能是这</code><code><span style="font-family: Arial;">3</span></code><code>个方法里最好的一个。它成功分离了关注点，也没有滥用内存和</code><code><span style="font-family: Arial;">CPU</span></code><code>，但还是效率很低，</code><code><span style="font-family: Arial;">AccessDecisionVoter</span></code><code>和最终的业务方法都要自己来调用</code><code><span style="font-family: Arial;">DAO</span></code><code>方法来获取</code><code><span style="font-family: Arial;">Customer</span></code><code>对象。一次业务方法调用要访问两次</code><code><span style="font-family: Arial;">DAO</span></code><code>很明显也不是你想要的。另外，上面提到的每一种方法你都要自己从头来编写自己的访问控制列表（</code><code><span style="font-family: Arial;">ACL</span></code><code>）持久化和业务逻辑。</code></p>
		<p>幸运地，还有另外一个选择，下面我们来讨论一下这个选择。</p>
		<h2>24.2. <span style="font-family: 黑体;">关键概念</span></h2>
		<p>
				<span style="font-family: Arial;">Spring Security</span>的<span style="font-family: Arial;">ACL</span>服务发布为<code><span style="font-family: Arial;">spring-security-acl-xxx.jar</span></code><code>。要使用</code><span style="font-family: Arial;">Spring Security</span>的域对象安全，你要把这个包加入到你的<span style="font-family: Arial;">classpath</span>中。</p>
		<p>
				<span style="font-family: Arial;">Spring Security</span>的域对象安全以访问控制列表（<span style="font-family: Arial;">ACL</span>）为核心概念。你系统里的每个域对象都有自己的<span style="font-family: Arial;">ACL</span>，这个<span style="font-family: Arial;">ACL</span>记录了谁能或不能访问该域对象。<span style="font-family: Arial;">Spring Security</span>为你的应用带来<span style="font-family: Arial;">3</span>个主要的<span style="font-family: Arial;">ACL</span>相关能力。</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>提供一条可以高效地为你所有的域对象获取<span style="font-family: Arial;">ACL</span>条目（以及修改<span style="font-family: Arial;">ACL</span>）的途径；</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>提供一条在方法被调用前保证给定用户有访问你的域对象许可的途径；</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>提供一条在方法被调用后保证给定用户有访问你的域对象许可的途径；</p>
		<p>正如第一点所说，<span style="font-family: Arial;">Spring Security</span>的<span style="font-family: Arial;">ACL</span>模块的主要能力之一是提供一个高性能获取<span style="font-family: Arial;">ACL</span>的途径。这个<span style="font-family: Arial;">ACL repository</span>的能力是非常重要的，因为你系统中的每一个域对象可能有若干个访问控制条目，每个<span style="font-family: Arial;">ACL</span>又可能是从其他<span style="font-family: Arial;">ACL</span>继承而来——树型结构（这很常用，<span style="font-family: Arial;">Spring Security</span>提供了很容易使用的支持）。<span style="font-family: Arial;">Spring Security</span>的<span style="font-family: Arial;">ACL</span>模块已经很小心的考虑了设计以满足高性能的<span style="font-family: Arial;">ACL</span>检索，它利用了可插接的缓存模块，死锁最小化的数据库更新，独立于<span style="font-family: Arial;">ORM</span>框架（我们使用直接<span style="font-family: Arial;">JDBC</span>），适当的包装，以及透明的数据库更新。</p>
		<p>数据库的设计是以<span style="font-family: Arial;">ACL</span>模块的操作为中心的，让我们来看看该模块的实现里缺省使用的<span style="font-family: Arial;">4</span>个主要数据表。下面列出在一个典型的<span style="font-family: Arial;">Spring Security ACL</span>部署中的数据表，以数据量大小排序，行数最多的在最后面：</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<span style="font-family: Arial;">ACL_SID</span>使我们能够在系统中唯一定义任何<span style="font-family: Arial;">principal</span>或<span style="font-family: Arial;">authority</span>（“<span style="font-family: Arial;">SID</span>”表示“<span style="font-family: Arial;">Security IDentity</span>”）。主键是<span style="font-family: Arial;">ID</span>，<span style="font-family: Arial;">SID</span>的文字表示，以及一个表示该<span style="font-family: Arial;">SID</span>是<span style="font-family: Arial;">principal</span>名还是<code><span style="font-family: Arial;">GrantedAuthority</span></code><code>的标识。每个</code><code><span style="font-family: Arial;">principal</span></code><code>或</code><code><span style="font-family: Arial;">GrantedAuthority</span></code><code>都有一个对应的记录。当在接受许可的上下文中使用的时候，</code><code><span style="font-family: Arial;">SID</span></code><code>通常被称为“接收者（</code><span style="font-family: Arial;">recipient</span><code>）”。</code></p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<span style="font-family: Arial;">ACL_CLASS</span>使我们能够在系统中唯一定义任何域对象类。主键是<span style="font-family: Arial;">ID</span>，然后是<span style="font-family: Arial;">CLASS</span>（<span style="font-family: Arial;">java</span>类名）。每个我们想要为其存储<span style="font-family: Arial;">ACL</span>许可的类有一个记录。</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<span style="font-family: Arial;">ACL_OBJECT_IDENTITY</span>存储系统里每个域对象实例的信息。其中的列包括<span style="font-family: Arial;">ID</span>；一个到表<span style="font-family: Arial;">ACL_CLASS </span>的外键<span style="font-family: Arial;">OBJECT_ID_CLASS</span>；一个使我们知道是为哪个<span style="font-family: Arial;">ACL_CLASS</span>类实例提供信息的唯一标识<span style="font-family: Arial;">OBJECT_ID_IDENTITY</span>；父对象，一个到<span style="font-family: Arial;">ACL_SID</span>的外键<span style="font-family: Arial;">OWNER_SID</span>表示该域对象的所有者；<span style="font-family: Arial;">ENTRIES_INHERITING</span>表示是否允许<span style="font-family: Arial;">ACL</span>条目从<span style="font-family: Arial;">ACL</span>父条目继承。</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>最后，<span style="font-family: Arial;">ACL_ENTRY</span>存储为每个<span style="font-family: Arial;">recipient</span>分配的权限。它的列包括一个到表<span style="font-family: Arial;">ACL_OBJECT_IDENTITY</span>的外键，<span style="font-family: Arial;">recipient(</span>例如一个到<span style="font-family: Arial;">ACL_SID</span>的外键<span style="font-family: Arial;">)</span>，是否需要审计，以及一个表示许可是授予还是拒绝的“整数位掩码”（许可可能包括多个方面，如<span style="font-family: Arial;">view, edit, delete</span>）。每个<span style="font-family: Arial;">recipient</span>对每个域对象的许可都有一个记录</p>
		<p>
				<span style="font-family: Arial;">
						<!--[if gte vml 1]>

<![endif]-->
				</span>
		</p>
		<p>
				<img alt="" src="../../images/blogjava_net/algogz/spring.security.22.3.png" height="397" width="592" />
				<br />
		</p>
		<p>上一段中提到，<span style="font-family: Arial;">ACL</span>系统使用了“整数位掩码”。不要担心，你不需要知道这些数字指向的具体位移来使用<span style="font-family: Arial;">ACL</span>系统，只需要知道我们有<span style="font-family: Arial;">32</span>个开关可以打开或关闭就可以了（一个<span style="font-family: Arial;">int</span>数值<span style="font-family: Arial;">4</span>个<span style="font-family: Arial;">byte</span>，共<span style="font-family: Arial;">32</span>个<span style="font-family: Arial;">bits</span>）。每一个位代表一个<span style="font-family: Arial;">permission</span>，缺省地，这些<span style="font-family: Arial;">permission</span>是：读（<span style="font-family: Arial;">bit 0</span>），写（<span style="font-family: Arial;">bit 1</span>），创建（<span style="font-family: Arial;">bit 2</span>），删除（<span style="font-family: Arial;">bit 3</span>）和管理（<span style="font-family: Arial;">bit 4</span>）。如果你要使用其他<span style="font-family: Arial;">permission</span>，可以很容易的实现自己的<span style="font-family: Arial;">permission</span>实例，<span style="font-family: Arial;">ACL</span>框架的其余部分不需要具备你定义的扩展的知识，即可完成操作。</p>
		<p>明白我们采用这种“整数位掩码”对你的系统中域对象的数量是完全没有影响这一点是很重要的。我们的<span style="font-family: Arial;">permission</span>只能使用<span style="font-family: Arial;">32</span>个<span style="font-family: Arial;">bit</span>，但是你可以有数以十亿计的域对象（这也意味着会有数以十亿计的记录在<span style="font-family: Arial;">ACL_OBJECT_IDENTITY</span>表中，<span style="font-family: Arial;">ACL_ENTRY</span>表的记录则更多）。我们特别说明这一点是因为发现有些用户错误的以为我们要为每个潜在的域对象使用一个<span style="font-family: Arial;">bit</span>，这是不对的。</p>
		<p>现在我们已经提供了一个<span style="font-family: Arial;">ACL</span>系统的基本概览，以及在表结构上看起来的样子，现在让我们来看看关键接口。关键接口列表如下：</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<span style="font-family: Arial;">Acl</span>：每一个域对象有且仅有一个<span style="font-family: Arial;">ACL</span>的对象，它内部拥有<code><span style="font-family: Arial;">AccessControlEntry</span></code>，并知道<span style="font-family: Arial;">Acl</span>的所有者。<span style="font-family: Arial;">Acl</span>不直接指向域对象，而是指向一个<code><span style="font-family: Arial;">ObjectIdentity</span></code><code>。</code><code><span style="font-family: Arial;">Acl</span></code><code>是存储在</code><span style="font-family: Arial;">ACL_OBJECT_IDENTITY</span>表中的。</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<code>
						<span style="font-family: Arial;">AccessControlEntry</span>
				</code>
				<code>：一个</code>
				<code>
						<span style="font-family: Arial;">Acl</span>
				</code>
				<code>包含多个</code>
				<code>
						<span style="font-family: Arial;">AccessControlEntry</span>
				</code>，在<span style="font-family: Arial;">ACL</span>框架中，我们常常把它简称为<span style="font-family: Arial;">ACE</span>。每个<span style="font-family: Arial;">ACE</span>都指向一组<span style="font-family: Arial;">Permission</span>，<span style="font-family: Arial;">Sid</span>和<span style="font-family: Arial;">Acl</span>。<span style="font-family: Arial;">ACE</span>可以是<span style="font-family: Arial;">granting</span>或<span style="font-family: Arial;">non-granting</span>的，同时包含有审计的相关设置。<span style="font-family: Arial;">ACE</span>保存在<span style="font-family: Arial;">ACL_ENTRY</span>表中。</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<code>
						<span style="font-family: Arial;">Permission</span>
				</code>
				<code>：</code>
				<code>
						<span style="font-family: Arial;">Permission</span>
				</code>
				<code>表示一个不可变的位掩码，并为位掩码机制和信息输出提供方便的功能。上面提到的</code>
				<code>
						<span style="font-family: Arial;">5</span>
				</code>
				<code>个基本的</code>
				<code>
						<span style="font-family: Arial;">Permission</span>
				</code>
				<span style="font-family: Arial;">(bits 0 </span>到<span style="font-family: Arial;"> 4)</span><code>包含在</code><code><span style="font-family: Arial;">BasePermission</span></code><code>类中。</code></p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<code>
						<span style="font-family: Arial;">Sid</span>
				</code>
				<code>：</code>
				<code>
						<span style="font-family: Arial;">ACL</span>
				</code>
				<code>模块需要参照到</code>
				<code>
						<span style="font-family: Arial;">principal</span>
				</code>
				<code>和</code>
				<code>
						<span style="font-family: Arial;">GrantedAuthority[]</span>
				</code>
				<code>。</code>
				<code>
						<span style="font-family: Arial;">Sid</span>
				</code>
				<code>接口提供实际安全对象（如</code>
				<code>
						<span style="font-family: Arial;">principal, role, group</span>
				</code>
				<code>等等）和</code>
				<code>
						<span style="font-family: Arial;">Acl</span>
				</code>
				<code>中实际内容的间接联系，简称“安全身份”。普通的实现包括有</code>
				<code>
						<span style="font-family: Arial;">PrincipalSid</span>
				</code>
				<code>（在</code>
				<code>
						<span style="font-family: Arial;">Authentication</span>
				</code>
				<code>中表示一个</code>
				<code>
						<span style="font-family: Arial;">principal</span>
				</code>
				<code>）和</code>
				<code>
						<span style="font-family: Arial;">GrantedAuthoritySid</span>
				</code>
				<code>。安全身份信息放在</code>
				<span style="font-family: Arial;">ACL_SID</span>表中。</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<code>
						<span style="font-family: Arial;">ObjectIdentity</span>
				</code>
				<code>：</code>
				<code>
						<span style="font-family: Arial;">ACL</span>
				</code>
				<code>模块中，内部用</code>
				<code>
						<span style="font-family: Arial;">ObjectIdentity</span>
				</code>
				<code>来表示每个域对象。缺省的实现是</code>
				<code>
						<span style="font-family: Arial;">ObjectIdentityImpl</span>
				</code>
				<code>。</code>
		</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<code>
						<span style="font-family: Arial;">AclService</span>
				</code>
				<code>：用于获取</code>
				<code>
						<span style="font-family: Arial;">ObjectIdentity</span>
				</code>
				<code>适用的</code>
				<code>
						<span style="font-family: Arial;">Acl</span>
				</code>
				<code>。在包含的实现（</code>
				<code>
						<span style="font-family: Arial;">JdbcAclService</span>
				</code>
				<code>）中，获取操作委派给</code>
				<code>
						<span style="font-family: Arial;">LookupStrategy</span>
				</code>
				<code>。</code>
				<code>
						<span style="font-family: Arial;">LookupStrategy</span>
				</code>
				<code>为获取</code>
				<code>
						<span style="font-family: Arial;">ACL</span>
				</code>
				<code>信息提供高度优化的策略，使用批获取（</code>
				<code>
						<span style="font-family: Arial;">BasicLookupStrategy</span>
				</code>
				<code>），也支持用户实现以提供更好的性能，例如层次化查询和类似的以性能为中心的非</code>
				<code>
						<span style="font-family: Arial;">ANSI SQL</span>
				</code>
				<code>能力。</code>
		</p>
		<p style="margin-left: 36pt; text-indent: -18pt;">
				<span style="font-size: 10pt; font-family: Symbol;">
						<span>·<span style="font: 7pt &quot;Times New Roman&quot;;">        
</span></span>
				</span>
				<code>
						<span style="font-family: Arial;">MutableAclService</span>
				</code>
				<code>：允许修改</code>
				<code>
						<span style="font-family: Arial;">Acl</span>
				</code>
				<code>以便进行持久化，如果不是为了这个可以不必使用这个接口。</code>
		</p>
		<p>请注意我们提供的<span style="font-family: Arial;">AclService</span>和相关的数据库类都是使用<span style="font-family: Arial;">ANSI SQL</span>的。因此可以工作在所有主流数据库服务器上。在编写本文的时候，已经在<span style="font-family: Arial;">Hypersonic SQL, PostgreSQL, Microsoft SQL Server </span>和<span style="font-family: Arial;"> Oracle</span>上测试过。</p>
		<p>
				<span style="font-family: Arial;">Spring Security</span>发行包中有两个例子可以用来演示<span style="font-family: Arial;">ACL</span>模块。其一是<span style="font-family: Arial;">Contacts</span>例子，另外一个是<span style="font-family: Arial;">Document Management
System (DMS)</span>。我们建议你仔细看看这些例子。</p>
		<h2>24.3. <span style="font-family: 黑体;">入门</span></h2>
		<p>要开始使用<span style="font-family: Arial;">Spring Security</span>的<span style="font-family: Arial;">ACL</span>能力，你需要把你的<span style="font-family: Arial;">ACL</span>保存在某个地方。这要通过<span style="font-family: Arial;">Spring</span>实例化一个<code><span style="font-family: Arial;">DataSource</span></code><code>。然后该数据源被注入到</code><code><span style="font-family: Arial;">JdbcMutableAclService</span></code><code>和</code><code><span style="font-family: Arial;">BasicLookupStrategy</span></code><code>。后者提供了高性能的</code><code><span style="font-family: Arial;">ACL</span></code><code>获取能力，前者提供了可改变的能力。请参考发行包中任何一个例子来了解如何进行配置。你还需要往上一节中提到的四个表中填充数据（参考</code><code><span style="font-family: Arial;">ACL</span></code><code>例子看相关</code><code><span style="font-family: Arial;">SQL</span></code><code>语句）。</code></p>
		<p>创建所需数据表并实例化<code><span style="font-family: Arial;">JdbcMutableAclService</span></code><code>后，你还要确认你的领域模型支持与</code><span style="font-family: Arial;">Spring Security ACL</span>包互操作。很可能<code><span style="font-family: Arial;">ObjectIdentityImpl</span></code><code>已经提供了足够的支持，它提供了多种可用的方式。大部分的域对象会包含一个</code><code><span style="font-family: Arial;">public Serializable
getId()</span></code><code>方法。如果返回类型是</code><code><span style="font-family: Arial;">long</span></code><code>，或者和</code><code><span style="font-family: Arial;">long</span></code><code>兼容（例如</code><code><span style="font-family: Arial;">int</span></code><code>），你就不需要烦</code><code><span style="font-family: Arial;">ObjectIdentity</span></code><code>的问题了。</code><code><span style="font-family: Arial;">ACL</span></code><code>模块的很多部分都依赖于</code><code><span style="font-family: Arial;">long identifier</span></code><code>。如果没有使用</code><code><span style="font-family: Arial;">long</span></code><code>（或</code><code><span style="font-family: Arial;">int</span></code><code>，</code><code><span style="font-family: Arial;">byte</span></code><code>等），你有机会要重新实现几个类。我们不打算在</code><span style="font-family: Arial;">Spring Security ACL</span>模块中<code>支持非</code><code><span style="font-family: Arial;">long identifier</span></code><code>，因为</code><code><span style="font-family: Arial;">long</span></code><code>和所有的数据库</code><code><span style="font-family: Arial;">sequence</span></code><code>兼容，也是最为常用的</code><code><span style="font-family: Arial;">identifier</span></code><code>数据类型，同时有足够的长度支持通常的应用场景。</code></p>
		<p>下面的代码展示如何创建一个<span style="font-family: Arial;">Acl</span>，或修改一个已存在的<span style="font-family: Arial;">Acl</span>：</p>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">// Prepare the information we'd like in our access control entry (ACE)</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">Sid sid = new PrincipalSid("Samantha");</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">Permission p = BasePermission.ADMINISTRATION;</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">// Create or update the relevant ACL</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">MutableAcl acl = null;</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">try {</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"> acl = (MutableAcl) aclService.readAclById(oi);</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">} catch (NotFoundException nfe) {</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"> acl = aclService.createAcl(oi);</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">}</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">// Now grant some permissions via an access control entry (ACE)</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">acl.insertAce(acl.getEntries().length, p, sid, true);</span>
		</pre>
		<pre>
				<span style="background-color: rgb(217, 217, 217); background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; -moz-background-size: auto auto; font-size: 10.5pt; font-family: Arial; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">aclService.updateAcl(acl);</span>
		</pre>
		<p>在上面的例子中，我们获取的<span style="font-family: Arial;">ACL</span>是和一个标识（<span style="font-family: Arial;">identifer</span>）为<span style="font-family: Arial;">44</span>的<span style="font-family: Arial;">"Foo"</span>域对象联系在一起的。我们增加一个<span style="font-family: Arial;">ACE</span>以便一个叫<span style="font-family: Arial;">"Samantha"</span>的<span style="font-family: Arial;">principal</span>能<span style="font-family: Arial;">"administer"</span>该对象。除了<span style="font-family: Arial;">insertAce</span>方法，这段代码不需要再多加说明。它的第一个参数是新的<span style="font-family: Arial;">ACE</span>要插入到<span style="font-family: Arial;">Acl</span>的什么位置。上面的例子中，我们把它放到最后。最后一个参数是一个表示该<span style="font-family: Arial;">ACE</span>授权或拒绝的<span style="font-family: Arial;">boolean</span>值。大部分时候应该为授权（<span style="font-family: Arial;">true</span>），但是如果为拒绝（<span style="font-family: Arial;">false</span>），该<span style="font-family: Arial;">permission</span>会被有效的关闭。</p>
		<p>
				<span style="font-family: Arial;">Spring Security</span>没有在<span style="font-family: Arial;">DAO</span>或<span style="font-family: Arial;">repository</span>中为自动创建、更新或删除<span style="font-family: Arial;">ACL</span>提供任何特别集成。你要为域对象编写像上面这样的代码。在你的业务层中使用<span style="font-family: Arial;">AOP</span>来自动集成<span style="font-family: Arial;">ACL</span>信息和你业务层操作是值得考虑的。我们发现这是一种很有效的方式。</p>
		<span style="font-size: 10.5pt; font-family: 宋体;">一旦你已经使用了上面的技术来在数据库中存储一些</span>
		<span style="font-size: 10.5pt; font-family: Arial;">ACL</span>
		<span style="font-size: 10.5pt; font-family: 宋体;">信息，下一步就是实际如何使用这些</span>
		<span style="font-size: 10.5pt; font-family: Arial;">ACL</span>
		<span style="font-size: 10.5pt; font-family: 宋体;">信息作为你的授权决议逻辑的一部分。在这里你有好几个选择。你可以分别在方法调用前和调用后编写自己的</span>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">AccessDecisionVoter</span>
		</code>
		<code>
				<span style="font-size: 12pt;">或</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">AfterInvocationProvider</span>
		</code>
		<code>
				<span style="font-size: 12pt;">。这些类应该使用</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">AclService</span>
		</code>
		<code>
				<span style="font-size: 12pt;">来获取相关</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">ACL</span>
		</code>
		<code>
				<span style="font-size: 12pt;">，然后调用</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">Acl.isGranted(Permission[]
permission, Sid[] sids, boolean administrativeMode)</span>
		</code>
		<code>
				<span style="font-size: 12pt;">来决定是授权还是拒绝。你也可以使用我们的</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">AclEntryVoter</span>
		</code>
		<code>
				<span style="font-size: 12pt;">，</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">AclEntryAfterInvocationProvider</span>
		</code>
		<code>
				<span style="font-size: 12pt;">或</span>
		</code>
		<code>
				<span style="font-size: 12pt; font-family: Arial;">AclEntryAfterInvocationCollectionFilteringProvider</span>
		</code>
		<code>
				<span style="font-size: 12pt;">类。所有这些类都提供了基于声明的方式，运行时根据这些设定信息来进行评估，把你从编写代码中解放出来。请参考例子应用学习如何使用这些类。</span>
		</code>
<img src ="http://www.blogjava.net/libin2722/aggbug/329982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-08-26 16:01 <a href="http://www.blogjava.net/libin2722/articles/329982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>