??xml version="1.0" encoding="utf-8" standalone="yes"?>
h意!引用、{贴本文应注明原作者:Rosen Jiang 以及出处Q?/font>
http://www.aygfsteel.com/rosen
]]>
]]>
]]>
Z业的应用开发提供通用的、单一的终端用L陆接口,q且q行理多用户帐号基信息的应用开发是׃业来l护的?BR>
功能目标
用户登陆接口
为实现用L陆接口,XSSO 应该支持下列功能目标Q?BR>
接口应该与验证信息的处理cd无关?BR> 提供更改受控用户验证信息的功能。这意味着在最初更改用户密码会受到限制Q当然不排除来对其提供q种功能?BR> 提供用者徏立默认用户属性的支持。目前还不用从一l可用的用户属性选项来选择q些用户属性,当然不排除今后提供这U功能?BR> 当会话终止、注销时提供默认的清除服务?BR> 提供一U能让调用者通过从除?XSSO 实现以外的应用通知 XSSO 实现改变受控用户验证信息的服务?BR> XSSO 不能预先定W二ơ登陆操作的旉?BR> 注意Q做Z登陆操作Q意味着 XSSO 不需要所有登陆操作同时执行。这导致用户会话在所有可能的服务中被创徏Q即便某些服务用户ƈ没有实际的用?BR>
用户帐号理接口
Z实现用户帐号理接口QXSSO 应该支持下列功能目标Q?BR>
提供创徏、删除、修改用户帐L功能?BR> 提供为单个用户帐可|属性的功能?BR>
非功能性目?/FONT>
XSSO 的非功能性目标包括:
XSSO 应该与验证技术无兟뀂接口不能指定用特定的验证技术,不排除用Q何可能的验证技术?nbsp;
注意Q有些验证技术,比如按照挑战响应机制Q用h有的讑֤构成不会在W二ơ登陆动作时适用?BR> XSSO 应该与^台或操作pȝ无关。不排除 XSSO 会集成进常规桌面或常用服务器pȝQ甚臛_型机。当Ӟ也可以修改一?XSSO 再把它集成进那些桌面或服务器pȝ?BR>
安全目标
XSSO 实现的安全目标如下:
被部|之后,XSSO 不应反过来媄响所依赖的系l?BR> XSSO 不应有反q来冲击M独立pȝ服务的可用性?BR> XSSO 不应为当事h提供讉K用户帐号信息的途径Q因Z们不允许讉K处于受控安全域之内的那些信息?BR> 一?XSSO 实现要审核发生在 XSSO 上下文之内的所有安全相x动?BR> 一?XSSO 实现要保护由 XSSO 实现提供或生的所有安全相关信息,以便其他服务充分信Qq些安全信息的完整性和原始性,以便W二ơ登陆操作?BR> 当在各个lg内部以及lg与其他服务交互时QXSSO 应提供安全相关信息保护?BR>
范围之外
在当前的 XSSO 范围中,以下q些斚w不被考虑Q?BR>
提供跨越企业U系l边界的单点登陆?BR> 非用户配|验证信息的改变Q例如磁性徽章、智能卡{等?BR> 当登陆时用户属性的可选择性?BR> 配置和管理用户属性的可选集合(l)?BR> 当下面的用户帐号基础信息由其?XSSO 提供的功能所修改Ӟ需要维护单点登陆用户帐号基信息以及下面独立l护的用户帐号基信息的完整性?BR> 囑Ş化和命o行用L?XSSO 的基服务。这个工具可以是 XSSO 的一部分?BR>
译者注
典型的挑战响应机制应用在 HMAC(Keyed-Hashing for Message Authentication) 验证中。验证流E如下:
(1) 先由客户端向服务器发Z个验证请求?
(2) 服务器接到此h后生成一个随机数q过|络传输l客LQ此为挑战)?
(3) 客户端将收到的随机数提供l?ePassQ由 ePass 使用该随机数与存储在 ePass 中的密钥q行 HMAC-MD5 q算q得C个结果作证证据传l服务器Q此为响应)?
(4) 与此同时Q服务器也用该随机C存储在服务器数据库中的该客户密钥q行 HMAC-MD5 q算Q如果服务器的运结果与客户端传回的响应l果相同Q则认ؓ客户端是一个合法用戗?/FONT>
h意!引用、{贴本文应注明原译者:Rosen Jiang 以及出处Q?/FONT>http://www.aygfsteel.com/rosen
采用遗传方式的用L陆多pȝ
在历史上Q一个分布式计算机系l由各个lg作ؓ独立安全域装配而成。这些组件由包含兌操作pȝ和应用程序的独立q_l成?BR>
q些lg作ؓ官能上的独立域,l端用户必须自己独立辨别和验证他惌交互的那些域。该场景在上囑ַ有说明。终端用h初通过和主域(Primary DomainQ交互来建立会话。在上图中被U做d登陆QPrimary Domain Sign-OnQ,q且需要终端用h供一l可用的用户信息Q例如用户名和密码。主域会话典型的由操作系l会话外壛_代表l端用户环境的终端用h器上q行获得的(比如Q程序属性,环境变量和根目录Q。通过d会话外壳Q用户可以调用其他的域服务,比如q_或应用程序?BR>
要调用二U域QSecondary DomainQ服务,l端用户需要进行二U域登陆QSecondary Domain Sign-onQ。ƈ要求l端用户再次提供用户信息Q终端用户不得不引导一个独立的登陆对话框进行验证。二U域会话是典型的操作pȝ外壳或程序外壻I再一ơ代表终端用L境。从理的角度上看,采用遗传方式需要独立的理每个域,而且是多用户帐户理界面。权衡可用性和安全上的考量Q需要在企业中ؓ多个不同域部|一U协同机制以及可集成的用L陆功能以及用户帐L理功能。提供这U协同和集成的服务有益于Z业提供真实的开销Q通过Q?BR>
减少用户登陆到独立域p的操作时_同时也降低了q行登陆操作时失败的机率?BR> 通过减少必要的用户句柄和C多组认证消息Q增Z安全性?BR> 减少了时间的pQ改善了响应Q通过pȝ理员ؓpȝ增加、删除、修改用戯问权?BR> 通过增强pȝ理员维护用户帐号配|的完整性,来改善安全。采用协同一致的方式止或取消独立用戯问所有系l资源?/P>
单用L陆到多用?/STRONG>
q种服务被称做单点登陆(Single Sign-OnQ。不怎样Q该服务对于l端用户和管理方面都同样重要。这U方式在上图中有所体现。在单点登陆方式Q系l必M用户攉数据Q作Z登陆的一部分Q所有的w䆾和用户信息必L供给用户验证pȝQ以便每个二U域q行潜在的交互?BR>
q些信息q端用户作Z域登陆过E的一部分提供Q可在下面几个方面ؓ二域提供登陆:
直接方式Q用h供的信息直接作ؓ二域的W二ơ登陆的一部分?BR> 间接方式Q用h供的信息被用于找回存储在单点登陆理数据库上的其他用L标识和用户信息。取回的信息接着被用于基本的二域登陆操作?BR> 立即方式Q与二域徏立会话作为初始会话的立。意味着E序的客户将在第一ơ登陆操作时同时自动调用q徏立通信?BR> 临时存储或缓存,应用于终端用户偶请求二U域服务的情c?BR>
从管理的角度来看Q单点登陆模式提供一U单一用户理界面Q所有的lg域将以协同和同步的方式管理?BR>
单点登陆模式在安全方面的重要意义在于Q?BR>
二域与d的信dp:
正确地断al端用户的n份和验证信息?BR> 保护Z用未l许可的二域而验证终端用戯n份的验证信息?BR>
当主、从域之间通讯受到威胁Q比如中途拦截或丢失QeavsdroppingQ引起可能的伪装dQ验证信息应被保护v来?BR>
h意!引用、{贴本文应注明原译者:Rosen Jiang 以及出处Q?/FONT>http://www.aygfsteel.com/rosen
?/span>
Spring 1.1.1
开始,
EHCache
׃ZU通用~存解决Ҏ集成q?/span>
Spring
?/span>
我将C拦截器的例子Q它能把Ҏq回的结果缓存v来?/span>
利用
Spring IoC
配置
EHCache
?/span> Spring 里配|?/span> EHCache 很简单。你只需一?/span> ehcache.xml 文gQ该文g用于配置 EHCache Q?/span>
<ehcache>
<!—设|缓存文?.data 的创\径?/font>
如果该\径是 Java pȝ参数Q当前虚拟机会重新赋倹{?/font>
下面的参数这栯释:
下列属性是 defaultCache 必须的:
maxInMemory - 讑֮内存中创建对象的最大倹{?br /> eternal - 讄元素Q译注:内存中对象)是否怹ȝ。如果是Q将忽略?br /> 旉制且元素怸消亡?br /> timeToIdleSeconds - 讄某个元素消亡前的停顿旉?br /> 也就是在一个元素消亡之前,两次讉K旉的最大时间间隔倹{?br /> q只能在元素不是怹ȝ时有效(译注Q如果对象永恒不灭,?br /> 讄该属性也无用Q?br /> 如果该值是 0 意味着元素可以停顿无穷长的旉?br /> timeToLiveSeconds - 为元素设|消亡前的生存时间?br /> 也就是一个元素从构徏到消亡的最大时间间隔倹{?br /> q只能在元素不是怹ȝ时有效?br /> overflowToDisk - 讄当内存中~存辑ֈ maxInMemory 限制时元素是否可写到盘
<cache name="org.taha.cache.METHOD_CACHE"
user.home ?用户ȝ?br /> user.dir ?用户当前工作目录
java.io.tmpdir ?默认临时文g路径 -->
<diskStore path="java.io.tmpdir"/>
<!—缺省缓存配|。CacheManager 会把q些配置应用到程序中?/font>
上?br /> -->
maxElementsInMemory="300"
eternal="false"
timeToIdleSeconds="500"
timeToLiveSeconds="500"
overflowToDisk="true"
/>
</ehcache>
拦截器将使用 ?b>org.taha.cache.METHOD_CACHE? 区域~存Ҏq回l果。下面利?/span> Spring IoC ?/span> bean 来访问这一区域?/span>
<!-- ====================== ~存 ======================= -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="configLocation">
<value>classpath:ehcache.xml</value>
</property>
</bean>
<property name="cacheManager">
<ref local="cacheManager"/>
</property>
<property name="cacheName">
<value>org.taha.cache.METHOD_CACHE</value>
</property>
</bean>
构徏我们?/span>
MethodCacheInterceptor
该拦截器实现 org.aopalliance.intercept.MethodInterceptor 接口。一?/span> q行h (kicks-in) Q它首先查被拦截Ҏ是否被配|ؓ可缓存的。这可选择性的配置惌~存?/span> bean Ҏ。只要调用的Ҏ配置为可~存Q拦截器ؓ该方法生?/span> cache key q检查该Ҏq回的结果是否已~存。如果已~存Q就q回~存的结果,否则再次调用被拦截方法,q缓存结果供下次调用?/span>
org.taha.interceptor.MethodCacheInterceptor
/*
package org.taha.interceptor;
import java.io.Serializable;
import org.aopalliance.intercept.MethodInterceptor;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import net.sf.ehcache.Cache;
/**
private Cache cache;
/**
/**
/**
logger.debug("looking for method result in cache");
//cache method result
/**
return sb.toString();
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.springframework.util.Assert;
import net.sf.ehcache.Element;
* @author <a href="
mailto:irbouh@gmail.com">Omar
Irbouh</a>
* @since 2004.10.07
*/
public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean {
private static final Log logger = LogFactory.getLog(MethodCacheInterceptor.class);
* 讄~存?br /> */
public void setCache(Cache cache) {
this.cache = cache;
}
* 查是否提供必要参数?br /> */
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "A cache is required. Use setCache(Cache) to provide one.");
}
* L?br /> * 如果某方法可被缓存就~存其结?br /> * Ҏl果必须是可序列化的(serializable)
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
String targetName = invocation.getThis().getClass().getName();
String methodName = invocation.getMethod().getName();
Object[] arguments = invocation.getArguments();
Object result;
String cacheKey = getCacheKey(targetName, methodName, arguments);
Element element = cache.get(cacheKey);
if (element == null) {
//call target/sub-interceptor
logger.debug("calling intercepted method");
result = invocation.proceed();
logger.debug("caching result");
element = new Element(cacheKey, (Serializable) result);
cache.put(element);
}
return element.getValue();
}
* creates cache key: targetName.methodName.argument0.argument1...
*/
private String getCacheKey(String targetName,
String methodName,
Object[] arguments) {
StringBuffer sb = new StringBuffer();
sb.append(targetName)
.append(".").append(methodName);
if ((arguments != null) && (arguments.length != 0)) {
for (int i=0; i<arguments.length; i++) {
sb.append(".")
.append(arguments[i]);
}
}
}
}
MethodCacheInterceptor
代码说明了:
使用
MethodCacheInterceptor
下面摘录了怎样配置 MethodCacheInterceptor Q?/span>
<bean id="methodCacheInterceptor" class="org.taha.interceptor.MethodCacheInterceptor">
<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<bean id="myBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="cache">
<ref local="methodCache" />
</property>
</bean>
<property name="advice">
<ref local="methodCacheInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*methodOne</value>
<value>.*methodTwo</value>
</list>
</property>
</bean>
<property name="target">
<bean class="org.taha.beans.MyBean"/>
</property>
<property name="interceptorNames">
<list>
<value>methodCachePointCut</value>
</list>
</property>
</bean>
译注
如果你要~存的方法是 findXXXQ那么正则表辑ּ应该q样写:?*find.*”?br />
夏昕所著?/span>
Hibernate
开发指南》,其中他这hq?/span>
EHCache
配置文g的:
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000" //Cache中最大允怿存的数据数量
eternal="false" //Cache中数据是否ؓ帔R
timeToIdleSeconds="120" //~存数据钝化旉
timeToLiveSeconds="120" //~存数据的生存时?br /> overflowToDisk="true" //内存不Ӟ是否启用盘~存
/>
</ehcache>
h意!引用、{贴本文应注明原译者:Rosen Jiang 以及出处Q?/font>http://www.aygfsteel.com/rosen