简单的最美

来源:百度文库 编辑:神马文学网 时间:2024/04/19 13:52:44
关于作者

用户名:fdc_messenger
笔名:简单的最美
地区: 北京-北京
日历  2006年5月19日
日 一 二 三 四 五 六
快速登录
+ 用户名:
+ 密 码:

快速通道
博采梦之城
博客搜索

最新文章
• 关于Acegi文档翻译与笔记 • Acegi文档与阅读笔记-5 • Acegi文档与阅读笔记 • Acegi文档与阅读笔记-4 • Acegi文档与阅读笔记-3 • Acegi文档与阅读笔记-2 • Acegi文档阅读与笔记-1 • 我的老婆 • 买车 • 已锁定
文章索引
2004年索引2005年索引2006年索引
在线留言
• 苦恼的人:大哥我有一个关于spring ide 的配置和使用的问题一直没有解决如果你能帮我你可以告诉我的你MSN吗我是wsy_123@hotmail.com 你能回答我一些问题吗 2006-04-10 14:17:29
昵 称:
最新评论
java resource
spring 框架
apache org
netbeans IDE
hibernate
acegi security
ireport
jasperreports
osworkflow
quartz
访问统计: 2358
文章个数:5
评论个数:-1
留言条数:0




Powered by BlogDriver 2.1
简单的最美
文章
总目录|默认分类 |个人生活杂记 |java与J2EE |我的汽车人生 |
关于Acegi文档翻译与笔记
与其说是笔记不如说是在无奈的情况下出此下策。以前看类似的技术文档从来就不需要进行翻译。但是这次是在是受不了了。写的比中国人写的英语还要复杂。不得已只好在阅读的同时将理解的写成文字记录下来,进而帮助自己理解。
这里只是在Acegi 1.0rc的基础上进行的,如果有什么图片之类的没有看见,请到Acegi网站上下载压缩包,里面有全部的相关文档!但愿我的理解是正确的,如果有什么误导大家的,那就不好意思,对不起了!希望对你有一点点帮助!
累了,休息!
哦,你在阅读是一定要确保你对Spring有一个基本了、正确的理解。否则,理解它将是比较困难的。
- 作者:简单的最美 2005年12月29日, 星期四 17:02回复(0) |引用(0)加入博采
Acegi文档与阅读笔记-5
就像前面简要提到的一样,所有的认证实现都需要存储一组对象。这组对象表示的是已经被分配给主体的权限。这组对象被添加到Authentication对象中,并在以后进行权限判断时被读取。
As briefly mentioned in the Authentication section, all Authentication implementations are required to store an array of GrantedAuthority objects. These represent the authorities that have been granted to the principal. The GrantedAuthority objects are inserted into the Authentication object by the AuthenticationManager and are later read by AccessDecisionManagers when making authorization decisions.
Acegi安全系统自带了一个GrantedAuthority实现--GrantedAuthorityImpl。它允许在GrantedAuthority中的任何内容被转换为字符串。安全系统中自带的所有都是哟个此GrantedAuthorityImpl组装Authentication对象。
一个“复杂”的应该是这样一个实现,它保存了一组操作和权限限定--这些都被应用于不同的客户帐号数字。要将这个复杂的GrantedAuthority表示成一个字符串将会是非常的复杂,所以基于如此情况getAuthority()方法应该返回null。必须对任何明确指出,为了能够理解此GrantedAuthority的内容,它应该特定的支持此GrantedAuthority实现。
此方法允许代表一个的准确的字符串表示。由于以一个字符串的形式返回,使得能够被大多数容易的“解读”。如果一个不能被准确的表示成为一个字符串,则此就被认为是“复杂的”并且方法必须放回一个空值(null)
AccessDecisionManager被AbstractSecurityInterceptor所调用,它负责对最终的存取控制做决定。AccessDecisionManager接口包括三个方法:
The AccessDecisionManager is called by the AbstractSecurityInterceptor and is responsible for making final access control decisions. The AccessDecisionManager interface contains three methods:
在应用启动的时候被调用,以确定是否此AccessDecisionManager能够处理传递过来的ConfigAttribute。被安全拦截器调用以确认配置的AccessDecisionManager是否支持拦截器将要拦截的此种类型的安全对象。
从第一个方法我们可以看到,所有的信息同他方法参数的形式传递给AccessDecisionManager。特别的,将secure对象传入使它能够观测这些参数实际的安全对象中的情况。让我们假设安全对象是MethodInvocation。它可以查询到任意的客户资料,然后在AccessDecisionManager中执行某种安全逻辑以确定主体是否被允许在此客户上执行操作。如果存取被否决了则抛出一个AccessDeniedException。
用户可以实现自己的AccessDecisionManager以控制授权管理的方方面面,Acegi安全系统自带了几个实现--基于投票方式。图示四展示了这几个相关的类。
Whilst users can implement their own AccessDecisionManager to control all aspects of authorization, the Acegi Security System for Spring includes several AccessDecisionManager implementations that are based on voting. Figure 4 illustrates the relevant classes.
实现一个自定义的是可以的。Acegi安全系统的单元测试中提供了几个例子,包括。将会弃权,如果找不到配置。如果要进行表决,则它会通过查询以获取Contact对象的拥有者。如果它的拥有者与主体相匹配则表决通过。它只是简单的对拥有者与主体进行比较。所有这一切只是通过几行代码完成并示范了此结构灵活的授权模块。
上面的例子中,我们在方法拦截器上基于某些方法定义了。当这些方法被调用时,上面定义的表决器将会表决授权允许还是否决。表决器将会在方法引用中寻找第一个类型是的参数,然后将此参数传递给AclManager。AclManager将会返回一组应用在当前上的存取控制列表(ACL)。假定ACL包括上面列出的一个,表决器将会授权允许存取。如果ACL没有包括任何一个依靠此voter的定义,则表决器会否决此次存取活动。是非常重要的一个类,它允许你构建真正意义上的复杂的应用系统---域对象的安全完全定义的。如果你有兴趣学习更多的冠以Acegi安全系统的ACL能力以及如何更好的应用它的知识的话,请仔细阅读ACL和章节。另外仔细研究例子。
是Acegi自带的另外一个具体的Voter。它与Acegi的(后面将讨论)进行了整合。这个voter被设计的可以在同一个应用上下文中存在多个实例,如下所示:
Acegi安全系统提供了两个。会对以开始的任何进行表决。如果一个返回的字符串表示精确的与一个或者多个以,则它将被授权允许。如果没有找到任何一个以开头的ConfigAttribute与之精确匹配,则否决。如果没有ConfigAttribute以开头,则弃权。RoleVoter进行匹配时是大小写敏感的。
当然实现一个定制的也是可以的,让它使用一种完全不同的表决统计机制。例如,从一个特殊的接收表决信息,从另外一个接收否决信息。
实际的实现返回一个整数值,可能的值会是静态常量。如果对于一个授权决定不作表态,它应该返回,如果它要表态,则必须是两者之一。
有三个方法:
使用这种方式,一系列的实现被用在授权决定上。然后根据他们的“投票”评估决定是否要抛出一个异常。
Acegi安全系统自带了几个JSP标签库以方便jsp的书写。这些标签库是关于授权和其他不同服务的。
The Acegi Security System for Spring comes bundled with several JSP tag libraries that eases JSP writing. The tag libraries are known as authz and provide a range of different services.
将需要控制的内容包括在里面,如果当前主体具有某种的话就使之有效。
下面的jsp片段演示的如何使用
AuthorizeTag is used to include content if the current principal holds certain GrantedAuthoritys.
The following JSP fragment illustrates how to use the AuthorizeTag:
由于需要所有的属性都为true,所以这就允许你创建更复杂的授权情节。例如,你可以在同一个标签中这样声明,这样你就可以阻止新的管理员看见标签内部的内容了。然而要注意使用要比在你的设计中添加一个NOT条件判定要简单的多。^_^
标签库逻辑上会将所有的参数进行“与”操作。这就意味着如果你使用多个属性时,必须所有的属性都为‘true’,标签体内的内容才会被输出。不要使用了随后又添加一个,否则你会从来都不可能看见标签里面的内容。
你可能已经注意到每一个属性你都可以列出多个角色。只需要将他们用逗号分隔开。忽略空格
标签声明了以下特征:
如果主体被授权具有权限,则标签体的内容将会被输出。">Del
被用作简单的在页面上输出当前主体的一些信息。
AuthenticationTag is used to simply output a property of the current principal‘s Authentication.getPrincipal() object to the web page.
此片段将会将主体的名字输出。在这里我们假设返回的是一个UserDetails对象,通常使用时都会使用此方式。
下面的jsp片段演示了如何使用此tag:
如果当前的主体对于指定的域对象定义了ACL,就被用作处理这些内容。
AclTag is used to include content if the current principal has a ACL to the indicated domain object.
如果当前的主体拥有对于“contact”对象的ACL其中包括允许16和允许1,则这个tag中的内容将被输出。这些数字实际上是作为的掩码出现的。如果想了解更多的ACL的功能请参阅Acegi文档中关于ACL部分。
下面的JSP片段展示了如何使用此tag: ">Del
所有的taglib都被包含在了文件中,在jar包中的目录下。这就意味着对于满足jsp1.2以上的web容器,你只需要简单的将jar包放在目录下,它就将是可用的了。如果你使用jsp1.1容器,你就需要在web.xml文件中对你的标签库进行声明,并且涓埃能过authz.tld放在目录下。下面的片段需要被添加到web.xml文件中:
Acegi给出了几种方式完成相似的授权工作,下面是通常建议的做法:
Given there are several ways to achieve similar authorization outcomes in the Acegi Security System for Spring, the following general recommendations are made:
- 作者:fdc_messenger 2005年12月29日, 星期四 16:40回复(0) |引用(0)加入博采
Acegi文档与阅读笔记
客户端代码需要一种方式对于Acegi安全系统证明它的安全性。这就是Authentication接口扮演的角色。Authentication接口包括三个重要的对象:principal(调用者的身份),credentials(证明调用者身份的证据,例如密码),授权给principal的权限(列表)。有客户端提供,授权列表有提供。
Authentication requires a way for client code to present its security identification to the Acegi Security System for Spring. This is the role of the Authentication interface. The Authentication interface holds three important objects: the principal (the identity of the caller), the credentials (the proof of the identity of the caller, such as a password), and the authorities that have been granted to the principal. The principal and its credentials are populated by the client code, whilst the granted authorities are populated by the AuthenticationManager.
对于主体(principal)的授权工作是通过进行的。接口将在下面关于授权的章节中被讨论。
如图三所示,Acegi安全系统包括了几个具体的实现:
在安全拦截器一节中我们提到从中的里面提取Authentication对象。紧接着就将它传递给。接口十分的简单:
As discussed in the Security Interception section, the AbstractSecurityInterceptor extracts the Authentication object from the SecurityContext in the SecurityContextHolder. This is then passed to an AuthenticationManager. The AuthenticationManager interface is very simple:
有几个子类,其中最重要的是后面两个异常表示主体已经发现(principal)但是证据没有通过检验还有认证被否决、拒绝。也会被使用,它表明认证系统不能处理请求(例如数据库不可用引起)。两个子类,虽然它们不是很常用。
的实现在认证失败的时候会抛出一个异常(),或者成功时返回一个组装成功的Authentication对象。特别要注意,返回的Authentication对象应该包括一组对象。安全拦截器将返回的、组装后的Authentication对象放回到中的SecurityContext里,用以替换原来的那个Authentication对象。
尽管最基本的接口使用户可以开发出自己的认证系统,但是用户完全可以考虑使用Acegi自带的简单实现。可以通过一组认证提供者的形式在bean定义中被配置:
Whilst the basic Authentication and AuthenticationManager interfaces enable users to develop their own authentication systems, users should consider using the provider-based authentication packages provided by the Acegi Security System for Spring. The key class, ProviderManager, is configured via the bean context with a list of AuthenticationProviders:
Acegi安全系统具有阻止同一主体并发访问同一web应用资源的能力。例如:你可以阻止用户“batman”同一时间内两次进行系统登录。
Acegi Security is able to stop the same principal authenticating to the same web application multiple times concurrently. Put differently, you can stop user "Batman" from logging into a web application twice at the same time.
Acegi安全系统自带了一个产品量级的实现---。这个能够验证,它通过数据存取对象获得Authentication的详细信息。
The Acegi Security System for Spring includes a production-quality AuthenticationProvider implementation called DaoAuthenticationProvider. This authentication provider is able to authenticate a UsernamePasswordAuthenticationToken by obtaining authentication details from a data access object configured at bean creation time:
返回一个Authentication对象,这个对象应该包括主体的属性集。主体既可以是一个字符串(例如用户名)或者是一个UserDetails对象(通过UserDetailsService获得)。缺省情况下UserDetails被返回,因为这样作将能够使使用应用可能会用到的一些信息,例如:用户的全名、邮件地址等。如果使用容器适配器或者你的系统已经使用字符串进行操作(例如版本0.6版本以前),你应该在应用上下文中将属性设置为true。
在进行设计时就已经决定在中不提供帐号锁定这样的功能,因为如果提供这样的功能就会大大增加了UserDetialsService接口的复杂性。例如:这需要增加一个方法记录用户认证尝试的次数。这个功能可以被应用系统提供得应用事件推送机制轻松的实现,系统事件机制将会在下文讨论。
实现起来是简单容易的,它应该能够使用户容易的提取认证信息---使用他们自己选择的持久化存取策略。
接口提供了一组getter方法获取有效的基本验证信息例如:用户名(username)、密码、授权、用户有效与否。系统本身提供了一个具体实现User。Acegi安全系统用户将需要决定是否书写他们自己的--返回UserDetails类型。通常情况下用户只需要直接使用它或者它的子类,但是在特殊的情况下(例如使用ORM)需要用户书写他们自己的UserDetail实现。UserDetails经常被用来存储额外的主体相关的属性(例如电话号码、email地址等信息),这样这些信息就能够容易被web视图所使用。
由于这个类要为提供存取的能力,所以它必须实现接口:
所有Acegi安全系统内的实现(当然也包括)都需要一个缓存对象。这个缓存对象能够从你喜欢的任何地方获得。尽管我们建议你使用Spring的工厂类--如上面所示的配置。如果使用Spring的工厂类,请参阅Spring的文档以获得更多的关于如何优化缓存的存储、内存使用、逐出策略、超时等信息。
除了上面提到的特性外,还支持可选的对于UserDetails对象的缓存功能。接口能够使将UserDetails对象放进cache中,并根据authentication试图获取相同用户的顺序从cache中提取它。缺省情况下使用--不进行缓存处理。一个非常有用的缓存实现也被提供了,,它的配置如下所示:
是可选的。为对从authentication存贮中提取的密码信息提供了加密、解密的功能。,我们可以理解成一个混淆器,它将authentication中保存的密码进行混淆组装,这样就可以进一步的提高了密码的安全性。Acegi安全系统提供的实现包括了等方式。另外有两个实现也同时被提供了,:使用相同的方式对密码进行编码,:它使用返回的UserDetials中的某个属性作为“salt”进行编码工作。想要知道详细的消息请参阅JavaDocs。
虽然使用和创建一个自己的UserDetailsService实现通过自己选定的持久化策略中提取信息的做法是非常简单的。但是很多的应用不需要这样的复杂性。我们可以通过在应用上下文中配置一个的手段完成此功能,配置样例如下所示:
Whilst it is easy to use the DaoAuthenticationProvider and create a custom UserDetailsService implementation that extracts information from a persistence engine of choice, many applications do not require such complexity. One alternative is to configure an authentication repository in the application context itself using the InMemoryDaoImpl:
还提供了一个方法,它允许你将详细配置信息放置在的Springbean定义中,或者是放置在外部的properties文件中。这种方式已经被证明在简单的应用系统中,如果有比较多的用户是,或者在开发期间配置变更了,但是不希望使用数据库作为完全的认证支持时是非常有用的。
userMap属性中包含了每一个用户的用户名、密码、一组授权、有效与否等关键字信息。使用逗号作为分隔符。用户名必须出现在等号的左边,密码必须出现在等号右面的第一个。有效与否(,大小写敏感)可以出现在第二个位置或者依次后面的任意位置。其他剩余的内容都会被当作授权对待---他们将会被创建成为对象(下文关于授权一节中将会进行详细讨论)。注意,如果一个用户没有密码或者没有被授权,则此用户不会被创建到存储中。
Acegi安全系统提供提供了了一个自带的authentication provider,它能够通过JDBC数据源获取authentication信息。典型的配置如下所示:
The Acegi Security System for Spring also includes an authentication provider that can obtain authentication information from a JDBC data source. The typical configuration for the JdbcDaoImpl is shown below:
如果缺省的schema不适合你的需要,提供了两个属性允许被进行sql脚本定制。你同样可以通过创建JdbcDaoImpl的子类的方式进行定制。详细信息请参阅相关的JavaDocs。
你可以通过修改上面例子中的的配置信息来使用不同的关系数据库。不管你使用什么数据库,但是一个标准的数据库schema必须被保证使用,就如在dbinit.txt中所示的。
Acegi安全系统提供了一个filter它能够处理那些已经被预验证过的请求。这个filter假定你正在使用Siteminder处理认证工作,并且你的应用被用作处理授权。直接用Siteminder处理授权在Acegi中还没有直接被支持。
Acegi Security provides a package able to delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This package is discussed in detail below.
Central to JAAS operation are login configuration files. To learn more about JAAS login configuration files, consult the JAAS reference documentation available from Sun Microsystems. We expect you to have a basic understanding of JAAS and its login configuration file syntax in order to understand this section.
The JaasAuthenticationProvider attempts to authenticate a user’s principal and credentials through JAAS.
Let’s assume we have a JAAS login configuration file, /WEB-INF/login.conf, with the following contents:
JAASTest { sample.SampleLoginModule required; };
Like all Acegi Security beans, the JaasAuthenticationProvider is configured via the application context. The following definitions would correspond to the above JAAS login configuration file:
/WEB-INF/login.conf JAASTest
The CallbackHandlers and AuthorityGranters are discussed below.
Most JAAS LoginModules require a callback of some sort. These callbacks are usually used to obtain the username and password from the user. In an Acegi Security deployment, Acegi Security is responsible for this user interaction (typically via a reference to a ContextHolder-managed Authentication object). The JAAS package for Acegi Security provides two default callback handlers, JaasNameCallbackHandler and JaasPasswordCallbackHandler. Each of these callback handlers implement JaasAuthenticationCallbackHandler. In most cases these callback handlers can simply be used without understanding the internal mechanics. For those needing full control over the callback behavior, internally JaasAutheticationProvider wraps these JaasAuthenticationCallbackHandlers with an InternalCallbackHandler. The InternalCallbackHandler is the class that actually implements JAAS?normal CallbackHandler interface. Any time that the JAAS LoginModule is used, it is passed a list of application context configured InternalCallbackHandlers. If the LoginModule requests a callback against the InternalCallbackHandlers, the callback is in-turn passed to the JaasAuthenticationCallbackHandlers being wrapped.
JAAS works with principals. Even “roles?are represented as principals in JAAS. Acegi Security, on the other hand, works with Authentication objects. Each Authentication object contains a single principal, and multiple GrantedAuthority[]s. To facilitate mapping between these different concepts, the Acegi Security JAAS package includes an AuthorityGranter interface. An AuthorityGranter is responsible for inspecting a JAAS principal and returning a String. The JaasAuthenticationProvider then creates a JaasGrantedAuthority (which implements Acegi Security’s GrantedAuthority interface) containing both the AuthorityGranter-returned String and the JAAS principal that the AuthorityGranter was passed. The JaasAuthenticationProvider obtains the JAAS principals by firstly successfully authenticating the user’s credentials using the JAAS LoginModule, and then accessing the LoginContext it returns. A call to LoginContext.getSubject().getPrincipals() is made, with each resulting principal passed to each AuthorityGranter defined against the JaasAuthenticationProvider.setAuthorityGranters(List) property. Acegi Security does not include any production AuthorityGranters given every JAAS principal has an implementation-specific meaning. However, there is a TestAuthorityGranter in the unit tests that demonstrates a simple AuthorityGranter implementation.
Acegi Security provides a web filter (org.acegisecurity.ui.webapp.SiteminderAuthenticationProcessingFilter) that can be used to process requests that have been pre-authenticated by Computer Associates‘ Siteminder. This filter assumes that you‘re using Siteminder for authentication, and your application (or backing datasource) is used for authorization. The use of Siteminder for authorization is not yet directly supported by Acegi.
最后我们需要告诉将包括在它的处理范围内。
注意,上面提到的期待这password被匹配。在这里,认证工作已经被Siteminder处理了并且你已经将用户名和密码规定了相同的头key值,所以你可以编写你的简单的认为用户名和密码匹配成功。这听起来好像降低了系统的安全性,但是记住,在你的系统接收到请求以前Siteminder已经对请求进行认证了,所以你的接下来的工作就只需要简单的分配角色和拦截器需要使用的其他的属性值,等等。
由于依赖于,所以我们需要对它进行定义:
纵观整个认证系统部分,由于大量的接口使用。对于一个新用户来说可能会感到困惑,认证系统的那部分可以被定制,通常来说,建议如下:
With the heavy use of interfaces throughout the authentication system (Authentication, AuthenticationManager, AuthenticationProvider and UserDetailsService) it might be confusing to a new user to know which part of the authentication system to customize. In general, the following is recommended:
Siteminder代理在你的web服务器中被设置,它它拦截用户对你的应用的首次请求。此代理会将此请求重定向到登录页面,只有认证成功之后你的应用才可以接收到此请求。认证过的请求被Siteminder 代理组装了一个或者多个http 头信息。下面你可以假设请求的头信息中包括用户身份的关键字为“SM_USER”,当然你的头部信息值可以是不同的,只要你对Siteminder进行相应的设置。
第一步,设置一个bean并且将一个赋予它,再者需要告诉它一旦用户成功或者失败了如何寻找到那里寻找Siteminder的用户名和密码的值。多数用户在Siteminder被验证成功后就不需要使用密码值了,所以典型的两种使用相同的头。
你还需要将的引用编织到定义中,如下所示:
web.xml中定义将会导致当HttpSession开始或者中止是,一个被推到Spring的应用上下文。这个机制是值得商榷的,因为它在session中止是允许被通告。
此外,你需要将添加到你的中,只需要一个属性:sessionRegistry,通常它指定为一个实例
为了使用,你需要在web.xml中进行如下配置工作:
Acegi安全系统提供了一个具体的AuthenticationProvider实现:
还有其他几个重要的功能。它整合了当前session处理支持,另外它还可以转换抛出的任何异常,并将推出一个适当的系统事件。这些事件可以在包下找到,高级用户可以通过配置属性改变从异常到事件的映射关系(通常条件下,这种特殊配置是不需要的,缺省情况下事件的传播途径是适当的,当你没有在应用上下文中配置ApplicationListener时,所有的事件将都会被忽略)
注意当在提供者列表中找不到一个合适的提供者处理到来的Authentication时,一个异常(将会被抛出。
会调用一系列的注册的实现,知道找到一个能够处理给定的Authentication(多态,注意)类。一旦符合条件的被确定,authentication请求就会马上被传送给它。经过处理后所要进行的要么是返回一个组装完好的Authentication对象,要么抛出一个异常。
- 作者:fdc_messenger 2005年12月29日, 星期四 16:39回复(1) |引用(0)加入博采
Acegi文档与阅读笔记-4
客户端代码需要一种方式对于Acegi安全系统证明它的安全性。这就是Authentication接口扮演的角色。Authentication接口包括三个重要的对象:principal(调用者的身份),credentials(证明调用者身份的证据,例如密码),授权给principal的权限(列表)。有客户端提供,授权列表有提供。
Authentication requires a way for client code to present its security identification to the Acegi Security System for Spring. This is the role of the Authentication interface. The Authentication interface holds three important objects: the principal (the identity of the caller), the credentials (the proof of the identity of the caller, such as a password), and the authorities that have been granted to the principal. The principal and its credentials are populated by the client code, whilst the granted authorities are populated by the AuthenticationManager.
对于主体(principal)的授权工作是通过进行的。接口将在下面关于授权的章节中被讨论。
如图三所示,Acegi安全系统包括了几个具体的实现:
在安全拦截器一节中我们提到从中的里面提取Authentication对象。紧接着就将它传递给。接口十分的简单:
As discussed in the Security Interception section, the AbstractSecurityInterceptor extracts the Authentication object from the SecurityContext in the SecurityContextHolder. This is then passed to an AuthenticationManager. The AuthenticationManager interface is very simple:
有几个子类,其中最重要的是后面两个异常表示主体已经发现(principal)但是证据没有通过检验还有认证被否决、拒绝。也会被使用,它表明认证系统不能处理请求(例如数据库不可用引起)。两个子类,虽然它们不是很常用。
的实现在认证失败的时候会抛出一个异常(),或者成功时返回一个组装成功的Authentication对象。特别要注意,返回的Authentication对象应该包括一组对象。安全拦截器将返回的、组装后的Authentication对象放回到中的SecurityContext里,用以替换原来的那个Authentication对象。
尽管最基本的接口使用户可以开发出自己的认证系统,但是用户完全可以考虑使用Acegi自带的简单实现。可以通过一组认证提供者的形式在bean定义中被配置:
Whilst the basic Authentication and AuthenticationManager interfaces enable users to develop their own authentication systems, users should consider using the provider-based authentication packages provided by the Acegi Security System for Spring. The key class, ProviderManager, is configured via the bean context with a list of AuthenticationProviders:
Acegi安全系统具有阻止同一主体并发访问同一web应用资源的能力。例如:你可以阻止用户“batman”同一时间内两次进行系统登录。
Acegi Security is able to stop the same principal authenticating to the same web application multiple times concurrently. Put differently, you can stop user "Batman" from logging into a web application twice at the same time.
Acegi安全系统自带了一个产品量级的实现---。这个能够验证,它通过数据存取对象获得Authentication的详细信息。
The Acegi Security System for Spring includes a production-quality AuthenticationProvider implementation called DaoAuthenticationProvider. This authentication provider is able to authenticate a UsernamePasswordAuthenticationToken by obtaining authentication details from a data access object configured at bean creation time:
返回一个Authentication对象,这个对象应该包括主体的属性集。主体既可以是一个字符串(例如用户名)或者是一个UserDetails对象(通过UserDetailsService获得)。缺省情况下UserDetails被返回,因为这样作将能够使使用应用可能会用到的一些信息,例如:用户的全名、邮件地址等。如果使用容器适配器或者你的系统已经使用字符串进行操作(例如版本0.6版本以前),你应该在应用上下文中将属性设置为true。
在进行设计时就已经决定在中不提供帐号锁定这样的功能,因为如果提供这样的功能就会大大增加了UserDetialsService接口的复杂性。例如:这需要增加一个方法记录用户认证尝试的次数。这个功能可以被应用系统提供得应用事件推送机制轻松的实现,系统事件机制将会在下文讨论。
实现起来是简单容易的,它应该能够使用户容易的提取认证信息---使用他们自己选择的持久化存取策略。
接口提供了一组getter方法获取有效的基本验证信息例如:用户名(username)、密码、授权、用户有效与否。系统本身提供了一个具体实现User。Acegi安全系统用户将需要决定是否书写他们自己的--返回UserDetails类型。通常情况下用户只需要直接使用它或者它的子类,但是在特殊的情况下(例如使用ORM)需要用户书写他们自己的UserDetail实现。UserDetails经常被用来存储额外的主体相关的属性(例如电话号码、email地址等信息),这样这些信息就能够容易被web视图所使用。
由于这个类要为提供存取的能力,所以它必须实现接口:
所有Acegi安全系统内的实现(当然也包括)都需要一个缓存对象。这个缓存对象能够从你喜欢的任何地方获得。尽管我们建议你使用Spring的工厂类--如上面所示的配置。如果使用Spring的工厂类,请参阅Spring的文档以获得更多的关于如何优化缓存的存储、内存使用、逐出策略、超时等信息。
除了上面提到的特性外,还支持可选的对于UserDetails对象的缓存功能。接口能够使将UserDetails对象放进cache中,并根据authentication试图获取相同用户的顺序从cache中提取它。缺省情况下使用--不进行缓存处理。一个非常有用的缓存实现也被提供了,,它的配置如下所示:
是可选的。为对从authentication存贮中提取的密码信息提供了加密、解密的功能。,我们可以理解成一个混淆器,它将authentication中保存的密码进行混淆组装,这样就可以进一步的提高了密码的安全性。Acegi安全系统提供的实现包括了等方式。另外有两个实现也同时被提供了,:使用相同的方式对密码进行编码,:它使用返回的UserDetials中的某个属性作为“salt”进行编码工作。想要知道详细的消息请参阅JavaDocs。
虽然使用和创建一个自己的UserDetailsService实现通过自己选定的持久化策略中提取信息的做法是非常简单的。但是很多的应用不需要这样的复杂性。我们可以通过在应用上下文中配置一个的手段完成此功能,配置样例如下所示:
Whilst it is easy to use the DaoAuthenticationProvider and create a custom UserDetailsService implementation that extracts information from a persistence engine of choice, many applications do not require such complexity. One alternative is to configure an authentication repository in the application context itself using the InMemoryDaoImpl:
还提供了一个方法,它允许你将详细配置信息放置在的Springbean定义中,或者是放置在外部的properties文件中。这种方式已经被证明在简单的应用系统中,如果有比较多的用户是,或者在开发期间配置变更了,但是不希望使用数据库作为完全的认证支持时是非常有用的。
userMap属性中包含了每一个用户的用户名、密码、一组授权、有效与否等关键字信息。使用逗号作为分隔符。用户名必须出现在等号的左边,密码必须出现在等号右面的第一个。有效与否(,大小写敏感)可以出现在第二个位置或者依次后面的任意位置。其他剩余的内容都会被当作授权对待---他们将会被创建成为对象(下文关于授权一节中将会进行详细讨论)。注意,如果一个用户没有密码或者没有被授权,则此用户不会被创建到存储中。
Acegi安全系统提供提供了了一个自带的authentication provider,它能够通过JDBC数据源获取authentication信息。典型的配置如下所示:
The Acegi Security System for Spring also includes an authentication provider that can obtain authentication information from a JDBC data source. The typical configuration for the JdbcDaoImpl is shown below:
如果缺省的schema不适合你的需要,提供了两个属性允许被进行sql脚本定制。你同样可以通过创建JdbcDaoImpl的子类的方式进行定制。详细信息请参阅相关的JavaDocs。
你可以通过修改上面例子中的的配置信息来使用不同的关系数据库。不管你使用什么数据库,但是一个标准的数据库schema必须被保证使用,就如在dbinit.txt中所示的。
Acegi安全系统提供了一个filter它能够处理那些已经被预验证过的请求。这个filter假定你正在使用Siteminder处理认证工作,并且你的应用被用作处理授权。直接用Siteminder处理授权在Acegi中还没有直接被支持。
Acegi Security provides a package able to delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This package is discussed in detail below.
Central to JAAS operation are login configuration files. To learn more about JAAS login configuration files, consult the JAAS reference documentation available from Sun Microsystems. We expect you to have a basic understanding of JAAS and its login configuration file syntax in order to understand this section.
The JaasAuthenticationProvider attempts to authenticate a user’s principal and credentials through JAAS.
Let’s assume we have a JAAS login configuration file, /WEB-INF/login.conf, with the following contents:
JAASTest { sample.SampleLoginModule required; };
Like all Acegi Security beans, the JaasAuthenticationProvider is configured via the application context. The following definitions would correspond to the above JAAS login configuration file:
/WEB-INF/login.conf JAASTest
The CallbackHandlers and AuthorityGranters are discussed below.
Most JAAS LoginModules require a callback of some sort. These callbacks are usually used to obtain the username and password from the user. In an Acegi Security deployment, Acegi Security is responsible for this user interaction (typically via a reference to a ContextHolder-managed Authentication object). The JAAS package for Acegi Security provides two default callback handlers, JaasNameCallbackHandler and JaasPasswordCallbackHandler. Each of these callback handlers implement JaasAuthenticationCallbackHandler. In most cases these callback handlers can simply be used without understanding the internal mechanics. For those needing full control over the callback behavior, internally JaasAutheticationProvider wraps these JaasAuthenticationCallbackHandlers with an InternalCallbackHandler. The InternalCallbackHandler is the class that actually implements JAAS?normal CallbackHandler interface. Any time that the JAAS LoginModule is used, it is passed a list of application context configured InternalCallbackHandlers. If the LoginModule requests a callback against the InternalCallbackHandlers, the callback is in-turn passed to the JaasAuthenticationCallbackHandlers being wrapped.
JAAS works with principals. Even “roles?are represented as principals in JAAS. Acegi Security, on the other hand, works with Authentication objects. Each Authentication object contains a single principal, and multiple GrantedAuthority[]s. To facilitate mapping between these different concepts, the Acegi Security JAAS package includes an AuthorityGranter interface. An AuthorityGranter is responsible for inspecting a JAAS principal and returning a String. The JaasAuthenticationProvider then creates a JaasGrantedAuthority (which implements Acegi Security’s GrantedAuthority interface) containing both the AuthorityGranter-returned String and the JAAS principal that the AuthorityGranter was passed. The JaasAuthenticationProvider obtains the JAAS principals by firstly successfully authenticating the user’s credentials using the JAAS LoginModule, and then accessing the LoginContext it returns. A call to LoginContext.getSubject().getPrincipals() is made, with each resulting principal passed to each AuthorityGranter defined against the JaasAuthenticationProvider.setAuthorityGranters(List) property. Acegi Security does not include any production AuthorityGranters given every JAAS principal has an implementation-specific meaning. However, there is a TestAuthorityGranter in the unit tests that demonstrates a simple AuthorityGranter implementation.
Acegi Security provides a web filter (org.acegisecurity.ui.webapp.SiteminderAuthenticationProcessingFilter) that can be used to process requests that have been pre-authenticated by Computer Associates‘ Siteminder. This filter assumes that you‘re using Siteminder for authentication, and your application (or backing datasource) is used for authorization. The use of Siteminder for authorization is not yet directly supported by Acegi.
最后我们需要告诉将包括在它的处理范围内。
注意,上面提到的期待这password被匹配。在这里,认证工作已经被Siteminder处理了并且你已经将用户名和密码规定了相同的头key值,所以你可以编写你的简单的认为用户名和密码匹配成功。这听起来好像降低了系统的安全性,但是记住,在你的系统接收到请求以前Siteminder已经对请求进行认证了,所以你的接下来的工作就只需要简单的分配角色和拦截器需要使用的其他的属性值,等等。
由于依赖于,所以我们需要对它进行定义:
纵观整个认证系统部分,由于大量的接口使用。对于一个新用户来说可能会感到困惑,认证系统的那部分可以被定制,通常来说,建议如下:
With the heavy use of interfaces throughout the authentication system (Authentication, AuthenticationManager, AuthenticationProvider and UserDetailsService) it might be confusing to a new user to know which part of the authentication system to customize. In general, the following is recommended:
Siteminder代理在你的web服务器中被设置,它它拦截用户对你的应用的首次请求。此代理会将此请求重定向到登录页面,只有认证成功之后你的应用才可以接收到此请求。认证过的请求被Siteminder 代理组装了一个或者多个http 头信息。下面你可以假设请求的头信息中包括用户身份的关键字为“SM_USER”,当然你的头部信息值可以是不同的,只要你对Siteminder进行相应的设置。
第一步,设置一个bean并且将一个赋予它,再者需要告诉它一旦用户成功或者失败了如何寻找到那里寻找Siteminder的用户名和密码的值。多数用户在Siteminder被验证成功后就不需要使用密码值了,所以典型的两种使用相同的头。
你还需要将的引用编织到定义中,如下所示:
web.xml中定义将会导致当HttpSession开始或者中止是,一个被推到Spring的应用上下文。这个机制是值得商榷的,因为它在session中止是允许被通告。
此外,你需要将添加到你的中,只需要一个属性:sessionRegistry,通常它指定为一个实例
为了使用,你需要在web.xml中进行如下配置工作:
Acegi安全系统提供了一个具体的AuthenticationProvider实现:
还有其他几个重要的功能。它整合了当前session处理支持,另外它还可以转换抛出的任何异常,并将推出一个适当的系统事件。这些事件可以在包下找到,高级用户可以通过配置属性改变从异常到事件的映射关系(通常条件下,这种特殊配置是不需要的,缺省情况下事件的传播途径是适当的,当你没有在应用上下文中配置ApplicationListener时,所有的事件将都会被忽略)
注意当在提供者列表中找不到一个合适的提供者处理到来的Authentication时,一个异常(将会被抛出。
会调用一系列的注册的实现,知道找到一个能够处理给定的Authentication(多态,注意)类。一旦符合条件的被确定,authentication请求就会马上被传送给它。经过处理后所要进行的要么是返回一个组装完好的Authentication对象,要么抛出一个异常。
- 作者:fdc_messenger 2005年12月29日, 星期四 16:38回复(0) |引用(0)加入博采
Acegi文档与阅读笔记-3
象上面高层设计提到的,每一个安全对象都有他们自己的安全拦截器---负责处理每一个接收到的请求。处理过程包括以下操作:
As described in the High Level Design section, each secure object has its own security interceptor which is responsible for handling each request. Handling involves a number of operations:
,开发人员只需要简单的添加适当的配置信息到应用上下文中。接下来就是将那些需要被进行安全保护的bean链入拦截器的控制范围。链接的动作是通过使用来完成的,就像spring其他方面使用的方式相仿。另一种选择是,Acegi提供了,它将和Spring的一起使用,它会自动的将依赖的bean链到拦截器上。的定义形式如下所示:
To secure MethodInvocations, developers simply add a properly configured MethodSecurityInterceptor into the application context. Next the beans requiring security are chained into the interceptor. This chaining is accomplished using Spring’s ProxyFactoryBean or BeanNameAutoProxyCreator, as commonly used by many other parts of Spring (refer to the sample application for examples). Alternatively, Acegi Security provides a MethodDefinitionSourceAdvisor which may be used with Spring‘s DefaultAdvisorAutoProxyCreator to automatically chain the security interceptor in front of any beans defined against the MethodSecurityInterceptor. The MethodSecurityInterceptor itself is configured as follows:
如上所示,定义中包含了对实例的引用,这些引用对象将在下文中被逐一进行讨论。在这里我们仍然定义了一个,虽然这完全是可选择性的。同时也配置了configuration attributes信息,这些将会比应用到不同的方法签名。在文档的高层设计部分我们对configuration attributes已经进行了全面的讨论。
对于使用开发人员需要在web.xml中添加一个它将代理到。一个典型的配置的例子如下所示:
The AspectJ security interceptor is very similar to the AOP Alliance security interceptor discussed in the previous section. Indeed we will only discuss the differences in this section.
The AspectJ interceptor is named AspectJSecurityInterceptor. Unlike the AOP Alliance security interceptor, which relies on the Spring application context to weave in the security interceptor via proxying, the AspectJSecurityInterceptor is weaved in via the AspectJ compiler. It would not be uncommon to use both types of security interceptors in the same application, with AspectJSecurityInterceptor being used for domain object instance security and the AOP Alliance MethodSecurityInterceptor being used for services layer security.
Let‘s first consider how the AspectJSecurityInterceptor is configured in the Spring application context:
true org.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER org.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
As you can see, aside from the class name, the AspectJSecurityInterceptor is exactly the same as the AOP Alliance security interceptor. Indeed the two interceptors can share the same objectDefinitionSource, as the ObjectDefinitionSource works with java.lang.reflect.Methods rather than an AOP library-specific class. Of course, your access decisions have access to the relevant AOP library-specific invocation (ie MethodInvocation or JoinPoint) and as such can consider a range of addition criteria when making access decisions (such as method arguments).
Next you‘ll need to define an AspectJ aspect. For example:
package org.acegisecurity.samples.aspectj; import org.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor; import org.acegisecurity.intercept.method.aspectj.AspectJCallback; import org.springframework.beans.factory.InitializingBean; public aspect DomainObjectInstanceSecurityAspect implements InitializingBean { private AspectJSecurityInterceptor securityInterceptor; pointcut domainObjectInstanceExecution(): target(PersistableEntity) && execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect); Object around(): domainObjectInstanceExecution() { if (this.securityInterceptor != null) { AspectJCallback callback = new AspectJCallback() { public Object proceedWithObject() { return proceed(); } }; return this.securityInterceptor.invoke(thisJoinPoint, callback); } else { return proceed(); } } public AspectJSecurityInterceptor getSecurityInterceptor() { return securityInterceptor; } public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) { this.securityInterceptor = securityInterceptor; } public void afterPropertiesSet() throws Exception { if (this.securityInterceptor == null) throw new IllegalArgumentException("securityInterceptor required"); } }
In the above example, the security interceptor will be applied to every instance of PersistableEntity, which is an abstract class not shown (you can use any other class or pointcut expression you like). For those curious, AspectJCallback is needed because the proceed(); statement has special meaning only within an around() body. The AspectJSecurityInterceptor calls this anonymous AspectJCallback class when it wants the target object to continue.
You will need to configure Spring to load the aspect and wire it with the AspectJSecurityInterceptor. A bean declaration which achieves this is shown below:

That‘s it! Now you can create your beans from anywhere within your application, using whatever means you think fit (eg new Person();) and they will have the security interceptor applied.
To secure FilterInvocations, developers need to add a filter to their web.xml that delegates to the SecurityEnforcementFilter. A typical configuration example is provided below:
注意,这里这个filter实际上是一个从filter到bean的代理。Acegi安全系统中绝大多数的filter都使用这个类。将会在filter一节中讲述它的更多内容。
- 作者:fdc_messenger 2005年12月29日, 星期四 16:37回复(0) |引用(0)加入博采
Acegi文档与阅读笔记-2
在Acegi安全系统发布0.9.0版本以前,使用的是一个ContextHolder保存上下文信息。Context(上下文)的一个具体子类---SecureContext定义了一个接口用于认证对象的存储。ContextHolder是一个ThreadLocal类型对象。一个更全面的关于在Acegi安全系统中ThreadLocal的用途的讨论将会在此文档的后面进行。在经过与其他的一些Spring开发人员进行了关于一致性问题讨论后ContextHolder和SecureContext在0.9.0版本中被移除了。关于这个问题可以查看一下内容:。有可能在一个相当长的时期内你会在一些正是的文档中继续看到“ContextHolder”,在这种情况下你可以简单的使用一下方式进行体会,使用,这样做的同时基本上不会改变你对你阅读的文档的原意。
Prior to release 0.9.0, Acegi Security used a ContextHolder to store a Context between sessions. A particular subclass of Context, SecureContext defined an interface used for storage of the Authentication object. The ContextHolder was a ThreadLocal. A fuller discussion of the ThreadLocal usage with Acegi Security follows in this document. ContextHolder and SecureContext was removed from 0.9.0 after discussion with other Spring developers for the sake of consistency. See for example http://article.gmane.org/gmane.comp.java.springframework.devel/8290 and JIRA task SEC-77. This history is mentioned as the long period ContextHolder was used will likely mean that certain documentation you encounter concerning Acegi Security might still refer to ContextHolder. Generally you can just substitute "SecurityContextHolder" for "ContextHolder", and "SecurityContext" for "SecureContext", and you‘ll have the primary meaning of such documentation.
Acegi安全系统使用SecurityContextHolder保存SecurityContext。SecurityContext包含了简单的对于认证对象(Authentication)的存取与设置方法(getter/setter)。所有的Acegi安全类都会通过查询SecurityContextHolder以获得当前的SecurityContext(当然,随即也就获得了主体对象)。SecurityContextHolder是一个ThreadLocal对象,这意味着它是与当前执行的线程紧密关联在一起的。
The Acegi Security System for Spring uses a SecurityContextHolder to store the SecurityContext. The SecurityContext contains a single getter/setter for Authentication. All Acegi Security classes query the SecurityContextHolder for obtaining the current SecurityContext (and in turn the principal). SecurityContextHolder is a ThreadLocal, meaning it is associated with the current thread of execution.
Acegi安全系统的核心思想是,中保存的内容(SecurityContext的一个具体实现)能够在web请求间存储。这就使得一个经过成功认证过的主体能够在随后一系列的请求序列中能一直被证明有效性,这一切都可以通过从SecurityContextHolder中提取SecurityContext从而获得Authentication对象。会不间断的自动复制定义良好的HttpSession属性到SecurityContextHolder,然后在每个请求结束之前将SecurityContextHolder中保存的内容复制回HttpSession中以备下一次到来的请求使用。
Central to Acegi Security‘s design is that the contents of the SecurityContextHolder (which is simply a SecurityContext implementation) can be stored between web requests. This is so that a successfully authenticated principal can be identified on subsequent requests through the Authentication stored inside the SecurityContext obtained from the SecurityContextHolder. The HttpSessionContextIntegrationFilter exists to automatically copy the contents of a well-defined HttpSession attribute into the SecurityContextHolder, then at the end of each request, copy the SecurityContextHolder contents back into the HttpSession ready for next request.
一个基本的同时也是一个非常普遍的错误是---将其他的Acegi Filter放在之前。Acegi安全系统的filters期待着能够修改在SecurityContextHolder内容中适当的信息,或者其他一些有必要在不同的请求间保存的信息(也就是)。这就是为什么必须要将放到第一位使用的原因。
到版本1.0.0,Acegi安全系统将会支持本地化的异常信息。这些异常信息包括认证错误、存取被拒绝(授权错误)。那些为开发人员所关注的异常和日值信息没有被本地化处理,它们被用英文在Acegi代码中硬编码在代码中。
From 1.0.0, Acegi Security supports localization of exception messages that end users are likely to see. Such exceptions include authentication failures and access being denied (authorization failures). Exceptions and logging that is focused on developers or system deployers (including incorrect attributes, interface contract violations, using incorrect constructors, startup time validation, debug-level logging) etc are not localized and instead are hard-coded in English within Acegi Security‘s code.
在包下有一个messages.properties文件。它将被ApplicationContext所引用,因为Acegi系统中实现了Spring的接口,并且在application context启动时这个消息处理器被期盼这被引用和插入。通常你需要去做的就是在你的应用上下文中定义一个bean并且这个bean应用找个消息源。例如如下所示:
- 作者:fdc_messenger 2005年12月29日, 星期四 16:35回复(0) |引用(0)加入博采
Acegi文档阅读与笔记-1
大多数的企业级应用有四种基本的安全需求。第一,需要对主体进行鉴别。第二,需要对web请求进行保护。第三,需要对服务层方法进行保护。第四,很多情况下需要对域对象实例进行保护。Acegi系统提供了一个通用的框架,它可以满足所有这四种企业安全级的需求。
Most enterprise applications have four basic security requirements. First, they need to be able to authenticate a principal. Second, they need to be able to secure web requests. Third, enterprise applications need to be able to secure services layer methods. Finally, quite often an enterprise application will need to secure domain object instances. Acegi Security provides a comprehensive framework for achieving all of these four common enterprise application security requirements.
Acegi安全系统本质上包括八个核心的功能部分:
象图示一中所示,Acegi安全系统当前支持三种安全对象。
As shown in the base of Figure 1, the Acegi Security System for Spring currently supports three secure objects.
第一种处理方式是AOP联盟的。开发人员通常使用这种安全对象保护他们的业务对象。为了使Spring类型的bean能够为MethodInvocation可用,这个bean只需要简单的被通过ProxyFactoryBean或者BeanNameAutoProxyCreator或者DefaultAdvisorAutoProxyCreator进行发布。大多数Spring开发者应该已经熟悉这种工作方式了,因为他们已经通过使用transactions和其他Spring方式熟悉了这种方式。
每一个安全对象能处理了无限数量的独立的请求。例如:MethodInvocation能够处理对于具有任意参数的任何方法的调用,与此同时FilterInvocation能够处理任何Http Url。
Every secure object can represent an infinite number of individual requests. For example, a MethodInvocation can represent the invocation of any method with any arguments, whilst a FilterInvocation can represent any HTTP URL.
Acegi安全系统需要记录将要被应用到安全对象上的可能的请求的配置设定。与将是两个全然不同的请求配置信息。相似的,相对于也是一个具有很大区别的配置安全请求信息。
- 作者:fdc_messenger 2005年12月29日, 星期四 16:34回复(0) |引用(0)加入博采
我的老婆
我的老婆!^_^,我还没有结婚呢!老婆,是在我心目中的老婆!
用一句老话来说,时光如电日月如梭,一转眼来到了2005年末,我也进入了一个尴尬的年龄32。每天都要聆听老妈的唠叨:不小了,成个家吧!邻居的阿姨们也热心的介绍不同的女子要我去见面。唉,老了!^_^。需要让大家操心了!
你是不是要求太高了?差不多,是个过日子的人就行了!你还等什么你看×××都结婚了,就剩下你了,你怎么不急呀!你。。。。不是有什么问题吧!我晕!让我变成聋子好了!
我的老婆!你快来吧,不是我不需要你,只是你的矜持让我一直没有看到你!
你能明白我看你的时候目不转睛不是在发呆而是在享受一种治疗眼睛快感!
你不絮絮叨叨,你只要说一遍我就明白了,你要发泄你的不满,只需要一个责备的眼神就足够了。
我不侃侃而谈,但是慢慢的、淡淡的聊天是个不错的对象。
我可能会过分的投入工作暂时忽略了你,但是哪只能是暂时的!老婆一定是比工作要重要的!^_^
“野蛮女友”我举双手反对,但是那分浪漫我很喜欢!
我决不允许你养成小猪的习惯,赖在床上睡懒觉!小心pp被打呀!没事你要和我到郊外远足。平时下班后我会专横的拉着你去锻炼身体!我渴望与你健康的相伴到白头!
我对你的要求不高,能够舒舒服服的在一起就好了!没事不要烦我!烦也要有点水平!^_^
- 作者:fdc_messenger 2005年12月5日, 星期一 09:41回复(0) |引用(0)加入博采
买车
摘要:发布不了呀查看全文
- 作者:fdc_messenger 2005年08月9日, 星期二 11:56回复(0) |引用(0)加入博采
已锁定
此日志的浏览权限已被作者锁定,请同作者联系,发送短消息,如果你的身份符合作者的要求,点击此处可以进行浏览
- 作者:fdc_messenger 2005年04月11日, 星期一 11:04回复(0) |引用(0)加入博采
Copyright©2003-2004 BOKEE.COM All rights reserved
_xyz