|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
Java编译的是字节码,跟C++相反,启动不够快,效率不够高,难以精确控制内存,但是优点是编程比C++容易,代码比较安全但是容易留下性能隐患,跨平台靠字节码在各个平台复制(一处编译到处调试)择要:单点登录(SSO)的手艺被愈来愈普遍地使用到各个范畴的软件体系傍边。本文从营业的角度剖析了单点登录的需乞降使用范畴;从手艺自己的角度剖析了单点登录手艺的外部机制和完成手腕,而且给出Web-SSO和桌面SSO的完成、源代码和具体解说;还从平安和功能的角度对现有的完成手艺举行进一步剖析,指出响应的风险和必要改善的方面。本文除从多个方面和角度给出了对单点登录(SSO)的周全剖析,还而且会商了怎样将现有的使用和SSO服务分离起来,可以匡助使用架构师和体系剖析职员从实质上熟悉单点登录,从而更好地计划出切合必要的平安架构。
关头字:SSO,Java,J2EE,JAAS
1甚么是单点上岸
单点登录(SingleSignOn),简称为SSO,是今朝对照盛行的企业营业整合的办理计划之一。SSO的界说是在多个使用体系中,用户只必要登录一次就能够会见一切互相信托的使用体系。
较年夜的企业外部,一样平常都有良多的营业撑持体系为其供应响应的办理和IT服务。比方财政体系为财政职员供应财政的办理、盘算和报表服务;人事体系为人事部门供应全公司职员的保护服务;各类营业体系为公司外部分歧的营业供应分歧的服务等等。这些体系的目标都是让盘算机来举行庞大烦琐的盘算事情,来替换人力的手工休息,进步事情效力和质量。这些分歧的体系常常是在分歧的时代建立起来的,运转在分歧的平台上;大概是由分歧厂商开辟,利用了各类分歧的手艺和尺度。假如举例说国际一出名的IT公司(名字隐往),外部共有60多个营业体系,这些体系包含两个分歧版本的SAP的ERP体系,12个分歧范例和版本的数据库体系,8个分歧范例和版本的操纵体系,和利用了3种分歧的防火墙手艺,另有数十种相互不克不及兼容的协定和尺度,你信任吗?不要嫌疑,这类情形实在十分广泛。每个使用体系在运转了数年今后,城市成为不成交换的企业IT架构的一部分,以下图所示。
<br>
跟着企业的开展,营业体系的数目在不休的增添,老的体系却不克不及容易的交换,这会带来良多的开支。其一是办理上的开支,必要保护的体系愈来愈多。良多体系的数据是互相冗余和反复的,数据的纷歧致性会给办理事情带来很年夜的压力。营业和营业之间的相干性也愈来愈年夜,比方公司的计费体系和财政体系,财政体系和人事体系之间都不成制止的有着亲切的干系。
为了下降办理的损耗,最年夜限制的重用已有投资的体系,良多企业都在举行着企业使用集成(EAI)。企业使用集成能够在分歧层面长进行:比方在数据存储层面上的“数据年夜会合”,在传输层面上的“通用数据互换平台”,在使用层面上的“营业流程整合”,和用户界面上的“通用企业流派”等等。现实上,还用一个层面上的集成变得愈来愈主要,那就是“身份认证”的整合,也就是“单点登录”。
一般来讲,每一个独自的体系城市有本人的平安系统和身份认证体系。整合之前,进进每一个体系都必要举行登录,如许的场合排场不但给办理上带来了很年夜的坚苦,在平安方面也埋下了严重的隐患。上面是一些出名的查询拜访公司显现的统计数据:
- 用户天天均匀16分钟花在身份考证义务上-材料IDS
- 频仍的IT用户均匀有21个暗码-材料NTAMonitorPasswordSurvey
- 49%的人写下了其暗码,而67%的人很少改动它们
- 每79秒呈现一同身份被窃事务-材料NationalSmallBusinessTravelAssoc
- 环球棍骗丧失每一年约12B-材料CommFraudControlAssoc
- 到2007年,身份办理市场将成倍增加至$4.5B-材料IDS
利用“单点登录”整合后,只必要登录一次就能够进进多个体系,而不必要从头登录,这不单单带来了更好的用户体验,更主要的是下降了平安的风险和办理的损耗。请看上面的统计数据:
- 进步IT效力:关于每1000个受管用户,每用户可节俭$70K
- 匡助台呼唤削减最少1/3,关于10K员工的公司,每一年能够节俭每用户$75,大概算计$648K
- 临盆力进步:每一个新员工可节俭$1K,每一个老员工可节俭$350�材料Giga
- ROI报答:7.5到13个月�材料Gartner
别的,利用“单点登录”仍是SOA时期的需求之一。在面向服务的架构中,服务和服务之间,程序和程序之间的通信大批存在,服务之间的平安认证是SOA使用的难点之一,应此创建“单点登录”的体系系统可以年夜年夜简化SOA的平安成绩,进步服务之间的互助效力。
2单点上岸的手艺完成机制
跟着SSO手艺的盛行,SSO的产物也是满天飞扬。一切出名的软件厂商都供应了响应的办理计划。在这里我其实不想先容本人公司(SunMicrosystems)的产物,而是对SSO手艺自己举行剖析,而且供应本人开辟这一类产物的办法和复杂演示。有关我写这篇文章的目标,请参考我的博客(http://yuwang881.blog.sohu.com/3184816.html)。
单点登录的机制实际上是对照复杂的,用一个实际中的例子做对照。颐和园是北京出名的旅游景点,也是我常往的中央。在颐和园外部有很多自力的景点,比方“姑苏街”、“佛喷鼻阁”和“德和园”,都能够在各个景点门口独自买票。良多旅客必要嬉戏一切德景点,这类买票体例很不便利,必要在每一个景点门口列队买票,钱包拿进拿出的,简单丧失,很不平安。因而尽年夜多半旅客选择在年夜门口买一张通票(也叫套票),就能够玩遍一切的景点而不必要从头再买票。他们只必要在每一个景点门口出示一下方才买的套票就可以够被同意进进每一个自力的景点。
单点登录的机制也一样,以下图所示,当用户第一次会见使用体系1的时分,由于还没有登录,会被引诱到认证体系中举行登录(1);依据用户供应的登录信息,认证体系举行身份效验,假如经由过程效验,应当前往给用户一个认证的凭证--ticket(2);用户再会见其余使用的时分(3,5)就会将这个ticket带上,作为本人认证的凭证,使用体系承受到哀求以后会把ticket送到认证体系举行效验,反省ticket的正当性(4,6)。假如经由过程效验,用户就能够在不必再次登录的情形下会见使用体系2和使用体系3了。
<br>
从下面的视图能够看出,要完成SSO,必要以下次要的功效:
- 一切使用体系共享一个身份认证体系。
一致的认证体系是SSO的条件之一。认证体系的次要功效是将用户的登录信息和用户信息库比拟较,对用户举行登录认证;认证乐成后,认证体系应当天生一致的认证标记(ticket),返还给用户。别的,认证体系还应当对ticket举行效验,判别其无效性。
- 一切使用体系可以辨认和提取ticket信息
要完成SSO的功效,让用户只登录一次,就必需让使用体系可以辨认已登录过的用户。使用体系应当能对ticket举行辨认和提取,经由过程与认证体系的通信,能主动判别以后用户是不是登录过,从而完成单点登录的功效。
下面的功效只是一个十分复杂的SSO架构,在实际情形下的SSO有着加倍庞大的布局。有两点必要指出的是:
- 单一的用户信息数据库并非必需的,有很多体系不克不及将一切的用户信息都会合存储,应当同意用户信息安排在分歧的存储中,以下图所示。现实上,只需一致认证体系,一致ticket的发生和效验,不管用户信息存储在甚么中央,都能完成单点登录。
<br>
- 一致的认证体系并非说只要单个的认证服务器,以下图所示,全部体系能够存在两个以上的认证服务器,这些服务器乃至能够是分歧的产物。认证服务器之间要经由过程尺度的通信协定,相互互换认证信息,就可以完成更初级其余单点登录。以下图,当用户在会见使用体系1时,由第一个认证服务器举行认证后,失掉由此服务器发生的ticket。当他会见使用体系4的时分,认证服务器2可以辨认此ticket是由第一个服务器发生的,经由过程认证服务器之间尺度的通信协定(比方SAML)来互换认证信息,仍旧可以完成SSO的功效。
<br>
3WEB-SSO的完成
跟着互联网的高速开展,WEB使用几近统治了尽年夜部分的软件使用体系,因而WEB-SSO是SSO使用傍边最为盛行。WEB-SSO有其本身的特性和上风,完成起来对照复杂易用。良多贸易软件和开源软件都有对WEB-SSO的完成。个中值得一提的是OpenSSO(https://opensso.dev.java.net),为用Java完成WEB-SSO供应架构指南和服务指南,为用户本人来完成WEB-SSO供应了实际的根据和完成的办法。
为何说WEB-SSO对照简单完成呢?这是有WEB使用本身的特性决意的。
尽人皆知,Web协定(也就是HTTP)是一个无形态的协定。一个Web使用由良多个Web页面构成,每一个页面都有独一的URL来界说。用户在扫瞄器的地点栏输出页面的URL,扫瞄器就会向WebServer往发送哀求。以下图,扫瞄器向Web服务器发送了两个哀求,请求了两个页面。这两个页面的哀求是分离利用了两个独自的HTTP毗连。所谓无形态的协定也就是体现在这里,扫瞄器和Web服务器会在第一个哀求完成今后封闭毗连通道,在第二个哀求的时分从头创建毗连。Web服务器其实不辨别哪一个哀求来自哪一个客户端,对一切的哀求都厚此薄彼,都是独自的毗连。如许的体例年夜年夜区分于传统的(Client/Server)C/S布局,在那样的使用中,客户端和服务器端会创建一个长工夫的公用的毗连通道。恰是由于有了无形态的特征,每一个毗连资本可以很快被其他客户端所重用,一台Web服务器才干够同时服务于不计其数的客户端。
<br>
可是我们一般的使用是有形态的。先不必提分歧使用之间的SSO,在统一个使用中也必要保留用户的登录身份信息。比方用户在会见页面1的时分举行了登录,可是方才也提到,客户真个每一个哀求都是独自的毗连,当客户再次会见页面2的时分,怎样才干告知Web服务器,客户方才已登录过了呢?扫瞄器和服务器之间有商定:经由过程利用cookie手艺来保护使用的形态。Cookie是能够被Web服务器设置的字符串,而且能够保留在扫瞄器中。以下图所示,当扫瞄器会见了页面1时,web服务器设置了一个cookie,并将这个cookie和页面1一同前往给扫瞄器,扫瞄器接到cookie以后,就会保留起来,在它会见页面2的时分会把这个cookie也带上,Web服务器接到哀求时也能读出cookie的值,依据cookie值的内容就能够判别和恢复一些用户的信息形态。
<br>
Web-SSO完整能够使用Cookie停止来完成用户登录信息的保留,将扫瞄器中的Cookie和上文中的Ticket分离起来,完成SSO的功效。
为了完成一个复杂的SSO的功效,必要两个部分的互助:
- 一致的身份认证服务。
- 修正Web使用,使得每一个使用都经由过程这个一致的认证服务来举行身份效验。
3.1WebSSO的样例
依据下面的道理,我用J2EE的手艺(JSP和Servlet)完成了一个具有Web-SSO的复杂样例。样例包括一个身份认证的服务器和两个复杂的Web使用,使得这两个Web使用经由过程一致的身份认证服务来完成Web-SSO的功效。此样例一切的源代码和二进制代码都能够从网站地点http://gceclub.sun.com.cn/wangyu/下载。
样例下载、安装部署和运转指南:
- Web-SSO的样例是由三个尺度Web使用构成,紧缩成三个zip文件,从http://gceclub.sun.com.cn/wangyu/web-sso/中下载。个中SSOAuth(http://gceclub.sun.com.cn/wangyu/web-sso/SSOAuth.zip)是身份认证服务;SSOWebDemo1(http://gceclub.sun.com.cn/wangyu/web-sso/SSOWebDemo1.zip)和SSOWebDemo2(http://gceclub.sun.com.cn/wangyu/web-sso/SSOWebDemo2.zip)是两个用来演示单点登录的Web使用。这三个Web使用之以是没有打成war包,是由于它们不克不及间接部署,依据读者的部署情况必要作出小小的修正。样例部署和运转的情况有必定的请求,必要切合Servlet2.3以上尺度的J2EE容器才干运转(比方Tomcat5,SunApplicationServer8,Jboss4等)。别的,身份认证服务必要JDK1.5的运转情况。之以是要用JDK1.5是由于笔者利用了一个线程平安的高功能的Java汇合类“ConcurrentMap”,只要在JDK1.5中才有。
- 这三个Web使用完整能够独自部署,它们能够分离部署在分歧的呆板,分歧的操纵体系和分歧的J2EE的产物上,它们完整是尺度的战争台有关的使用。可是有一个限定,那两台部署使用(demo1、demo2)的呆板的域名必要不异,这在前面的章节中会注释到cookie和domain的干系和怎样制造跨域的WEB-SSO
- 解紧缩SSOAuth.zip文件,在/WEB-INF/下的web.xml中请修正“domainname”的属性以反应实践的使用部署情形,domainname必要设置为两个单点登录的使用(demo1和demo2)所属的域名。这个domainname和以后SSOAuth服务部署的呆板的域名没有干系。我缺省设置的是“.sun.com”。假如你部署demo1和demo2的呆板没有域名,请输出IP地点或主机名(如localhost),可是假如利用IP地点或主机名也就意味着demo1和demo2必要部署到一台呆板上了。设置完后,依据你所选择的J2EE容器,大概必要将SSOAuth这个目次紧缩打包成war文件。用“jar-cvfSSOAuth.warSSOAuth/”就能够完成这个功效。
- 解紧缩SSOWebDemo1和SSOWebDemo2文件,分离在它们/WEB-INF/下找到web.xml文件,请修正个中的几个初始化参数
<init-param>
<param-name>SSOServiceURL</param-name>
<param-value>http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuth</param-value>
</init-param>
<init-param>
<param-name>SSOLoginPage</param-name>
<param-value>http://wangyu.prc.sun.com:8080/SSOAuth/login.jsp</param-value>
</init-param>
将个中的SSOServiceURL和SSOLoginPage修正成部署SSOAuth使用的呆板名、端标语和根路径(缺省是SSOAuth)以反应实践的部署情形。设置完后,依据你所选择的J2EE容器,大概必要将SSOWebDemo1和SSOWebDemo2这两个目次紧缩打包成两个war文件。用“jar-cvfSSOWebDemo1.warSSOWebDemo1/”就能够完成这个功效。
- 请输出第一个web使用的测试URL(test.jsp),比方http://wangyu.prc.sun.com:8080/SSOWebDemo1/test.jsp,假如是第一次会见,便会主动跳转到登录界面,以下图
<br>
- 利用体系自带的三个帐号之一登录(比方,用户名:wangyu,暗码:wangyu),便能乐成的看到test.jsp的内容:显现以后用户名和接待信息。
<br>
- 请接着在统一个扫瞄器中输出第二个web使用的测试URL(test.jsp),比方http://wangyu.prc.sun.com:8080/SSOWebDemo2/test.jsp。你会发明,不必要再次登录就可以看到test.jsp的内容,一样是显现以后用户名和接待信息,并且接待信息中明白的显现以后的使用称号(demo2)。
<br>
3.2WEB-SSO代码解说
3.2.1身份认证服务代码剖析
Web-SSO的源代码能够从网站地点http://gceclub.sun.com.cn/wangyu/web-sso/websso_src.zip下载。身份认证服务是一个尺度的web使用,包含一个名为SSOAuth的Servlet,一个login.jsp文件和一个failed.html。身份认证的一切服务几近都由SSOAuth的Servlet来完成了;login.jsp用来显现登录的页面(假如发明用户还没有登录过);failed.html是用来显现登录失利的信息(假如用户的用户名和暗码与信息数据库中的纷歧样)。
SSOAuth的代码以下面的列表显现,布局十分复杂,先看看这个Servlet的主体部分:
packageDesktopSSO;
importjava.io.*;
importjava.net.*;
importjava.text.*;
importjava.util.*;
importjava.util.concurrent.*;
importjavax.servlet.*;
importjavax.servlet.http.*;
publicclassSSOAuthextendsHttpServlet{
staticprivateConcurrentMapaccounts;
staticprivateConcurrentMapSSOIDs;
Stringcookiename="WangYuDesktopSSOID";
Stringdomainname;
publicvoidinit(ServletConfigconfig)throwsServletException{
super.init(config);
domainname=config.getInitParameter("domainname");
cookiename=config.getInitParameter("cookiename");
SSOIDs=newConcurrentHashMap();
accounts=newConcurrentHashMap();
accounts.put("wangyu","wangyu");
accounts.put("paul","paul");
accounts.put("carol","carol");
}
protectedvoidprocessRequest(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
PrintWriterout=response.getWriter();
Stringaction=request.getParameter("action");
Stringresult="failed";
if(action==null){
handlerFromLogin(request,response);
}elseif(action.equals("authcookie")){
StringmyCookie=request.getParameter("cookiename");
if(myCookie!=null)result=authCookie(myCookie);
out.print(result);
out.close();
}elseif(action.equals("authuser")){
result=authNameAndPasswd(request,response);
out.print(result);
out.close();
}elseif(action.equals("logout")){
StringmyCookie=request.getParameter("cookiename");
logout(myCookie);
out.close();
}
}
.....
}
从代码很简单看出,SSOAuth就是一个复杂的Servlet。个中有两个静态成员变量:accounts和SSOIDs,这两个成员变量都利用了JDK1.5中线程平安的MAP类:ConcurrentMap,以是这个样例必定要JDK1.5才干运转。Accounts用来寄存用户的用户名和暗码,在init()的办法中能够看到我给体系增加了三个正当的用户。在实践使用中,accounts应当是往数据库中或LDAP中取得,为了复杂起见,在本样例中我利用了ConcurrentMap在内存顶用程序创立了三个用户。而SSOIDs保留了在用户乐成的登录后所发生的cookie和用户名的对应干系。它的功效不言而喻:当用户乐成登录今后,再次会见其余体系,为了判别这个用户哀求所带的cookie的无效性,必要到SSOIDs中反省如许的映照干系是不是存在。
在次要的哀求处置办法processRequest()中,能够很分明的看到SSOAuth的一切功效
- 假如用户还没有登录过,是第一次登录本体系,会被跳转到login.jsp页面(在前面会注释怎样跳转)。用户在供应了用户名和暗码今后,就会用handlerFromLogin()这个办法来考证。
- 假如用户已登录过本体系,再会见其余使用的时分,是不必要再次登录的。由于扫瞄器会将第一次登录时发生的cookie和哀求一同发送。效验cookie的无效性是SSOAuth的次要功效之一。
- SSOAuth还能间接效验非login.jsp页面过去的用户名和暗码的效验哀求。这个功效是用于非web使用的SSO,这在前面的桌面SSO中会用到。
- SSOAuth还供应logout服务。
上面看看几个次要的功效函数:
privatevoidhandlerFromLogin(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
Stringusername=request.getParameter("username");
Stringpassword=request.getParameter("password");
Stringpass=(String)accounts.get(username);
if((pass==null)||(!pass.equals(password)))
getServletContext().getRequestDispatcher("/failed.html").forward(request,response);
else{
StringgotoURL=request.getParameter("goto");
StringnewID=createUID();
SSOIDs.put(newID,username);
Cookiewangyu=newCookie(cookiename,newID);
wangyu.setDomain(domainname);
wangyu.setMaxAge(60000);
wangyu.setValue(newID);
wangyu.setPath("/");
response.addCookie(wangyu);
System.out.println("loginsuccess,gotobackurl:"+gotoURL);
if(gotoURL!=null){
PrintWriterout=response.getWriter();
response.sendRedirect(gotoURL);
out.close();
}
}
}
handlerFromLogin()这个办法是用来处置来自login.jsp的登录哀求。它的逻辑很复杂:将用户输出的用户名和暗码与事后设定好的用户汇合(寄存在accounts中)比拟较,假如用户名或暗码不婚配的话,则前往登录失利的页面(failed.html),假如登录乐成的话,必要为用户以后的session创立一个新的ID,并将这个ID和用户名的映照干系寄存到SSOIDs中,最初还要将这个ID设置为扫瞄器可以保留的cookie值。
登录乐成后,扫瞄器会到哪一个页面呢?那我们回忆一下我们是怎样利用身份认证服务的。一样平常来讲我们不会间接会见身份服务的任何URL,包含login.jsp。身份服务是用来回护其他使用服务的,用户一样平常在会见一个受SSOAuth回护的Web使用的某个URL时,以后这个使用会发明以后的用户还没有登录,便强迫将也页面转向SSOAuth的login.jsp,让用户登录。假如登录乐成后,应当主动的将用户的扫瞄器指向用户最后想会见的谁人URL。在handlerFromLogin()这个办法中,我们经由过程吸收“goto”这个参数来保留用户最后会见的URL,乐成后便从头定向到这个页面中。
别的一个要申明的是,在设置cookie的时分,我利用了一个setMaxAge(6000)的办法。这个办法是用来设置cookie的无效期,单元是秒。假如不利用这个办法大概参数为正数的话,当扫瞄器封闭的时分,这个cookie就生效了。在这里我给了很年夜的值(1000分钟),招致的举动是:当你封闭扫瞄器(大概关机),下次再翻开扫瞄器会见方才的使用,只需在1000分钟以内,就不必要再登录了。我如许做是上面要先容的桌面SSO中所必要的功效。
其他的办法加倍复杂,这里就未几注释了。
3.2.2具有SSO功效的web使用源代码剖析
要完成WEB-SSO的功效,只要身份认证服务是不敷的。这点很明显,要想使多个使用具有单点登录的功效,还必要每一个使用自己的共同:将本人的身份认证的服务交给一个一致的身份认证服务-SSOAuth。SSOAuth服务中供应的各个办法就是供每一个到场SSO的Web使用来挪用的。
一样平常来讲,Web使用必要SSO的功效,应当经由过程以下的交互历程来挪用身份认证服务的供应的认证服务:
- Web使用中每个必要平安回护的URL在会见之前,都必要举行平安反省,假如发明没有登录(没有发明认证以后所带的cookie),就从头定向到SSOAuth中的login.jsp举行登录。
- 登录乐成后,体系会主动给你的扫瞄器设置cookie,证实你已登录过了。
- 当你再会见这个使用的必要回护的URL的时分,体系仍是要举行平安反省的,可是此次体系可以发明响应的cookie。
- 有了这个cookie,还不克不及证实你就必定有权限会见。由于有大概你已logout,大概cookie已过时了,大概身份认证服务重起过,这些情形下,你的cookie都大概有效。使用体系拿到这个cookie,还必要挪用身份认证的服务,来判别cookie时分真的无效,和以后的cookie对应的用户是谁。
- 假如cookie效验乐成,就同意用户会见以后哀求的资本。
以上这些功效,能够用良多办法来完成:
- 在每一个被会见的资本中(JSP或Servlet)中都到场身份认证的服务,来取得cookie,而且判别以后用户是不是登录过。不外这个笨办法没有人会用:-)。
- 能够经由过程一个controller,将一切的功效都写到一个servlet中,然后在URL映照的时分,映照到一切必要回护的URL汇合中(比方*.jsp,/security/*等)。这个办法可使用,不外,它的弱点是不克不及重用。在每一个使用中都要部署一个不异的servlet。
- Filter是对照好的办法。切合Servlet2.3以上的J2EE容器就具有部署filter的功效。(Filter的利用能够参考JavaWolrd的文章http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-filters.html)Filter是一个具有很好的模块化,可重用的编程API,用在SSO正符合不外。本样例就是利用一个filter来完成以上的功效。
packageSSO;
importjava.io.*;
importjava.net.*;
importjava.util.*;
importjava.text.*;
importjavax.servlet.*;
importjavax.servlet.http.*;
importjavax.servlet.*;
importorg.apache.commons.httpclient.*;
importorg.apache.commons.httpclient.methods.GetMethod;
publicclassSSOFilterimplementsFilter{
privateFilterConfigfilterConfig=null;
privateStringcookieName="WangYuDesktopSSOID";
privateStringSSOServiceURL="http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuth";
privateStringSSOLoginPage="http://wangyu.prc.sun.com:8080/SSOAuth/login.jsp";
publicvoidinit(FilterConfigfilterConfig){
this.filterConfig=filterConfig;
if(filterConfig!=null){
if(debug){
log("SSOFilter:Initializingfilter");
}
}
cookieName=filterConfig.getInitParameter("cookieName");
SSOServiceURL=filterConfig.getInitParameter("SSOServiceURL");
SSOLoginPage=filterConfig.getInitParameter("SSOLoginPage");
}
.....
.....
}
以上的初始化的源代码有两点必要申明:一是有两个必要设置的参数SSOServiceURL和SSOLoginPage。由于以后的Web使用极可能和身份认证服务(SSOAuth)不在统一台呆板上,以是必要让这个filter晓得身份认证服务部署的URL,如许才干往挪用它的服务。别的一点就是因为身份认证的服务挪用是要经由过程http协定来挪用的(在本样例中是如许计划的,读者完整能够计划本人的身份服务,利用其余挪用协定,如RMI或SOAP等等),一切笔者援用了apache的commons工具包(具体信息情会见apache的网站http://jakarta.apache.org/commons/index.html),个中的“httpclient”能够年夜年夜简化http挪用的编程。
上面看看filter的主体办法doFilter():
publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{
if(debug)log("SSOFilter:doFilter()");
HttpServletRequestrequest=(HttpServletRequest)req;
HttpServletResponseresponse=(HttpServletResponse)res;
Stringresult="failed";
Stringurl=request.getRequestURL().toString();
Stringqstring=request.getQueryString();
if(qstring==null)qstring="";
//反省http哀求的head是不是有必要的cookie
StringcookieValue="";
javax.servlet.http.Cookie[]diskCookies=request.getCookies();
if(diskCookies!=null){
for(inti=0;i<diskCookies.length;i++){
if(diskCookies.getName().equals(cookieName)){
cookieValue=diskCookies.getValue();
//假如找到了响应的cookie则效验其无效性
result=SSOService(cookieValue);
if(debug)log("foundcookies!");
}
}
}
if(result.equals("failed")){//效验失利或没有找到cookie,则必要登录
response.sendRedirect(SSOLoginPage+"?goto="+url);
}elseif(qstring.indexOf("logout")>1){//logout服务
if(debug)log("logoutaction!");
logoutService(cookieValue);
response.sendRedirect(SSOLoginPage+"?goto="+url);
}else{//效验乐成
request.setAttribute("SSOUser",result);
Throwableproblem=null;
try{
chain.doFilter(req,res);
}catch(Throwablet){
problem=t;
t.printStackTrace();
}
if(problem!=null){
if(probleminstanceofServletException)throw(ServletException)problem;
if(probleminstanceofIOException)throw(IOException)problem;
sendProcessingError(problem,res);
}
}
}
doFilter()办法的逻辑也长短常复杂的,在吸收到哀求的时分,先往查找是不是存在希冀的cookie值,假如找到了,就会挪用SSOService(cookieValue)往效验这个cookie的无效性。假如cookie效验不乐成大概cookie基本不存在,就会间接转到登录界面让用户登录;假如cookie效验乐成,就不会做任何拦阻,让此哀求举行下往。在设置文件中,有上面的一个节点暗示了此filter的URL映照干系:只拦阻一切的jsp哀求。
<filter-mapping>
<filter-name>SSOFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
上面另有几个次要的函数必要申明:
privateStringSSOService(Stringcookievalue)throwsIOException{
StringauthAction="?action=authcookie&cookiename=";
HttpClienthttpclient=newHttpClient();
GetMethodhttpget=newGetMethod(SSOServiceURL+authAction+cookievalue);
try{
httpclient.executeMethod(httpget);
Stringresult=httpget.getResponseBodyAsString();
returnresult;
}finally{
httpget.releaseConnection();
}
}
privatevoidlogoutService(Stringcookievalue)throwsIOException{
StringauthAction="?action=logout&cookiename=";
HttpClienthttpclient=newHttpClient();
GetMethodhttpget=newGetMethod(SSOServiceURL+authAction+cookievalue);
try{
httpclient.executeMethod(httpget);
httpget.getResponseBodyAsString();
}finally{
httpget.releaseConnection();
}
}
这两个函数次要是使用apache中的httpclient会见SSOAuth供应的认证服务来完效果验cookie和logout的功效。
其他的函数都很复杂,有良多都是我的IDE(NetBeans)替我主动天生的。
4以后计划的平安范围性
以后这个WEB-SSO的计划是一个对照复杂的雏形,次要是用来演示SSO的观点和申明SSO手艺的完成体例。有良多方面还必要完美,个中平安性长短常主要的一个方面。
我们说过,接纳SSO手艺的次要目标之一就是增强平安性,下降平安风险。由于接纳了SSO,在收集上传送暗码的次数削减,风险下降是明显的,可是以后的计划却有其他的平安风险。因为cookie是一个用户登录的独一凭证,对cookie的回护措施是体系平安的主要环节:
- cookie的长度和庞大度
在本计划中,cookie是有一个流动的字符串(我的姓名)加受骗前的工夫戳。如许的cookie很简单被假造和推测。怀有歹意的用户假如推测到正当的cookie就能够被看成已登录的用户,恣意会见权限局限内的资本
- cookie的效验和回护
在本计划中,固然暗码只需传输一次就够了,可cookie在收集中是常常传来传往。一些收集探测工具(如sniff,snoop,tcpdump等)能够很简单捕捉到cookie的数值。在本计划中,并没有思索cookie在传输时分的回护。别的对cookie的效验也过于复杂,其实不往反省发送cookie的来历事实是否是cookie最后的具有者,也就是说没法辨别一般的用户和仿制cookie的用户。
- 当个中一个使用的平安性欠好,其他一切的使用城市遭到平安威逼
由于有SSO,以是当某个处于SSO的使用被客攻破,那末很简单攻破其他处于统一个SSO回护的使用。
这些平安毛病在贸易的SSO办理计划中城市有所思索,供应相干的平安措施和回护手腕,比方Sun公司的AccessManager,cookie的庞大读和对cookie的回护都做得十分好。别的在OpneSSO(https://opensso.dev.java.net)的架构指南中也给出了部分平安措施的办理计划。
5以后计划的功效和功能范围性
除平安性,以后计划在功效和功能上都必要良多的改善:
- 以后所供应的登录认证形式只要一种:用户名和暗码,并且为了复杂,将用户名和暗码放在内存傍边。现实上,用户身份信息的来历应当是多种多样的,能够是来自数据库中,LDAP中,乃至于来自操纵体系本身的用户列表。另有良多其他的认证形式都是商务使用不成短少的,因而SSO的办理计划应当包含各类认证的形式,包含数字证书,Radius,SafeWord,MemberShip,SecurID等多种体例。最为天真的体例应当同意可拔出的JAAS框架来扩大身份认证的接口
- 我们编写的Filter只能用于J2EE的使用,而关于大批非Java的Web使用,却没法供应SSO服务。
- 在将Filter使用到Web使用的时分,必要对容器上的每个使用都要做响应的修正,从头部署。而加倍盛行的做法是Agent机制:为每个使用服务器安装一个agent,就能够将SSO功效使用到这个使用服务器中的一切使用。
- 以后的计划不克不及撑持分离位于分歧domain的Web使用举行SSO。这是由于扫瞄器在会见Web服务器的时分,仅仅会带上和以后web服务用具有不异domain称号的那些cookie。要供应跨域的SSO的办理计划有良多其他的办法,在这里就未几说了。Sun的AccessManager就具有跨域的SSO的功效。
- 别的,Filter的功能成绩也是必要器重的方面。由于Filter会截获每个切合URL映照划定规矩的哀求,取得cookie,考证其无效性。这一系列义务是对照损耗资本的,出格是考证cookie无效性是一个远程的http的挪用,来会见SSOAuth的认证服务,有必定的延时。因而在功能上必要做进一步的进步。比方在本样例中,假如将URL映照从“.jsp”改成“/*”,也就是说filter对一切的哀求都起感化,全部使用会变得十分慢。这是由于,页面傍边包括了各类静态元素如gif图片,CSS款式文件,和其他html静态页面,这些页面的会见都要经由过程filter往考证。而现实上,这些静态元素没有甚么平安上的需求,应当在filter中举行判别,不往效验这些哀求,功能会好良多。别的,假如在filter中加上必定的cache,而不必要每个cookie效验哀求都往远真个身份认证服务中实行,功能也能年夜幅度进步。
- 别的体系还必要良多其他的服务,如在内存中准时删除无用的cookie映照等等,都是一个严厉的办理计划必要思索的成绩。
6桌面SSO的完成
从WEB-SSO的观点延长开,我们能够把SSO的手艺拓展到全部桌面的使用,不单单范围在扫瞄器。SSO的观点和准绳都没有改动,只必要再做一点点的事情,就能够完成桌面SSO的使用。
桌面SSO和WEB-SSO一样,关头的手艺也在于怎样在用户登录事后保留登录的凭证。在WEB-SSO中,登录的凭证是靠扫瞄器的cookie机制来完成的;在桌面使用中,能够将登录的凭据保留就任何中央,只需一切SSO的桌面使用都共享这个凭据。
从网站能够下载一个复杂的桌面SSO的样例(http://gceclub.sun.com.cn/wangyu/desktop-sso/desktopsso.zip)和全体源码(http://gceclub.sun.com.cn/wangyu/desktop-sso/desktopsso_src.zip),固然复杂,可是它具有桌面SSO年夜多半的功效,略微加以扩大就能够成为本人的办理计划。
6.1桌面样例的部署
- 运转此桌面SSO必要三个条件前提:
a)WEB-SSO的身份认证使用应当正在运转,由于我们在桌面SSO傍边必要用到一致的认证服务
b)以后桌面必要运转Mozilla或Netscape扫瞄器,由于我们将ticket保留到mozilla的cookie文件中
c)必需在JDK1.4以上运转。(WEB-SSO必要JDK1.5以上)
- 解开desktopsso.zip文件,内里有两个目次bin和lib。
- bin目次下有一些剧本文件和设置文件,个中config.properties包括了三个必要设置的参数:
a)SSOServiceURL要指向WebSSO部署的身份认证的URL
b)SSOLoginPage要指向WebSSO部署的身份认证的登录页面URL
c)cookiefilepath要指向以后用户的mozilla所寄存cookie的文件
- 在bin目次下另有一个login.conf是用来设置JAAS登录模块,本样例供应了两个,读者能够恣意选择个中一个(也能够都选),再从头运转程序,检察登录认证的变更
- 在bin下的运转剧本大概必要作响应的修正
a)假如是在unix下,各个jar文件必要用“:”来离隔,而不是“;”
b)java运转程序必要安排在以后运转的路径下,不然必要加上java的路径全名。
6.2桌面样例的运转
样例程序包括三个复杂的Java把持台程序,这三个程序独自运转都必要登录。假如运转第一个命叫“GameSystem”的程序,提醒必要输出用户名和暗码:
<br>
效验乐成今后,便会显现以后登录的用户的基础信息等等。
<br>
这时候候再运转第二个桌面Java使用(mailSystem)的时分,就不必要再登录了,间接就显现出来方才登录的用户。
<br>
第三个使用是logout,运转它以后,用户便加入体系。再会见的时分,又必要从头登录了。请读者再制裁实行完logout以后,从头考证一下前两个使用的SSO:先运转第二个使用,再运转第一个,会看到不异的效果。
我们的样例并没有在这里留步,现实上,本样例不但可以和在几个Java使用之间SSO,还能和扫瞄器举行SSO,也就是将扫瞄器也当做是桌面的一部分。这对一些行业有着不小的吸引力。
这时候候再翻开Mozilla扫瞄器,会见之前提到的那两个WEB使用,会发明只需桌面使用假如登录过,Web使用就不必再登录了,并且能显现方才登录的用户的信息。读者能够在几个桌面和Web使用之间举行登录和logout的实验,看看它们之间的SSO。
<br>
6.3桌面样例的源码剖析
桌面SSO的样例利用了JAAS(要懂得JAAS的具体的信息请参考http://java.sun.com/products/jaas)。JAAS是对PAM(PluggableAuthenticationModule)的Java完成,来完成Java使用可插拔的平安认证模块。利用JAAS作为Java使用的平安认证模块有良多优点,最次要的是不必要修正源代码就能够改换认证体例。比方原本的Java使用假如利用JAAS的认证,假如必要使用SSO,只必要修正JAAS的设置文件就好了。如今在盛行的J2EE和其他Java的产物中,用户的身份认证都是经由过程JAAS来完成的。在样例中,我们就展现了这个功效。请看设置文件login.conf
DesktopSSO{
desktopsso.share.PasswordLoginModulerequired;
desktopsso.share.DesktopSSOLoginModulerequired;
};
当我们注解失落第二个模块的时分,只要第一个模块起感化。在这个模块的感化下,只要test用户(暗码是12345)才干登录。当我们注解失落第一个模块的时分,只要第二个模块起感化,桌面SSO才会起感化。
一切的Java桌面样例程序都是尺度JAAS使用,熟习JAAS的程序员会很快懂得。JAAS中次要的是登录模块(LoginModule)。上面是SSO登录模块的源码:
publicclassDesktopSSOLoginModuleimplementsLoginModule{
..........
privateStringSSOServiceURL="";
privateStringSSOLoginPage="";
privatestaticStringcookiefilepath="";
.........
在config.properties的文件中,我们设置了它们的值:
SSOServiceURL=http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuth
SSOLoginPage=http://wangyu.prc.sun.com:8080/SSOAuth/login.jsp
cookiefilepath=C:DocumentsandSettingsyw137672ApplicationDataMozillaProfilesdefaulthog6z1ji.sltcookies.txt
SSOServiceURL和SSOLoginPage成员变量指向了在Web-SSO顶用过的身份认证模块:SSOAuth,这就申明在桌面体系中我们试图和Web使用共用一个认证服务。而cookiefilepath成员变量则保守了一个“天机”:我们利用了Mozilla扫瞄器的cookie文件来保留登录的凭据。换句话说,和Mozilla共用了一个保留登录凭据的机制。之以是用Mozilla是应为它的Cookie文件格局复杂,很简单编程会见和修正恣意的Cookie值。(我试图剖析InternetExplorer的cookie文件但没有乐成。)
上面是登录模块DesktopSSOLoginModule的主体:login()办法。逻辑也长短常复杂:先用Cookie来上岸,假如乐成,则间接就进进体系,不然必要用户输出用户名和暗码来登录体系。
publicbooleanlogin()throwsLoginException{
try{
if(Cookielogin())returntrue;
}catch(IOExceptionex){
ex.printStackTrace();
}
if(passwordlogin())returntrue;
thrownewFailedLoginException();
}
上面是Cookielogin()办法的实体,它的逻辑是:先从Cookie文件中取得响应的Cookie值,经由过程身份效验服务效验Cookie的无效性。假如cookie无效就算登录乐成;假如不乐成或Cookie不存在,用cookie登录就算失利。
publicbooleanCookielogin()throwsLoginException,IOException{
StringcookieValue="";
intcookieIndex=foundCookie();
if(cookieIndex<0)
returnfalse;
else
cookieValue=getCookieValue(cookieIndex);
username=cookieAuth(cookieValue);
if(!username.equals("failed")){
loginSuccess=true;
returntrue;
}
returnfalse;
}
用用户名和暗码登录的办法要庞大一些,经由过程Callback的机制和屏幕输出输入举行信息交互,完成用户登录信息的猎取;猎取信息今后经由过程userAuth办法来挪用远端SSOAuth的服务来判断以后登录的无效性。
publicbooleanpasswordlogin()throwsLoginException{
//
//Sinceweneedinputfromauser,weneedacallbackhandler
if(callbackHandler==null){
thrownewLoginException("NoCallbackHandlerdefined");
}
Callback[]callbacks=newCallback[2];
callbacks[0]=newNameCallback("Username");
callbacks[1]=newPasswordCallback("Password",false);
//
//Callthecallbackhandlertogettheusernameandpassword
try{
callbackHandler.handle(callbacks);
username=((NameCallback)callbacks[0]).getName();
char[]temp=((PasswordCallback)callbacks[1]).getPassword();
password=newchar[temp.length];
System.arraycopy(temp,0,password,0,temp.length);
((PasswordCallback)callbacks[1]).clearPassword();
}catch(IOExceptionioe){
thrownewLoginException(ioe.toString());
}catch(UnsupportedCallbackExceptionuce){
thrownewLoginException(uce.toString());
}
System.out.println();
Stringauthresult="";
try{
authresult=userAuth(username,password);
}catch(IOExceptionex){
ex.printStackTrace();
}
if(!authresult.equals("failed")){
loginSuccess=true;
clearPassword();
try{
updateCookie(authresult);
}catch(IOExceptionex){
ex.printStackTrace();
}
returntrue;
}
loginSuccess=false;
username=null;
clearPassword();
System.out.println("Login:PasswordLoginModuleFAIL");
thrownewFailedLoginException();
}
CookieAuth和userAuth办法都是使用apahce的httpclient工具包和远程的SSOAuth举行http毗连,猎取服务。
privateStringcookieAuth(Stringcookievalue)throwsIOException{
Stringresult="failed";
HttpClienthttpclient=newHttpClient();
GetMethodhttpget=newGetMethod(SSOServiceURL+Action1+cookievalue);
try{
httpclient.executeMethod(httpget);
result=httpget.getResponseBodyAsString();
}finally{
httpget.releaseConnection();
}
returnresult;
}
privateStringuserAuth(Stringusername,char[]password)throwsIOException{
Stringresult="failed";
Stringpasswd=newString(password);
HttpClienthttpclient=newHttpClient();
GetMethodhttpget=newGetMethod(SSOServiceURL+Action2+username+"&password="+passwd);
passwd=null;
try{
httpclient.executeMethod(httpget);
result=httpget.getResponseBodyAsString();
}finally{
httpget.releaseConnection();
}
returnresult;
}
另有一个中央必要增补申明的是,在本样例中,用户名和暗码的输出城市在屏幕上显现明文。假如但愿用掩码情势来显现暗码,以进步平安性,请参考:http://java.sun.com/developer/technicalArticles/Security/pwordmask/
7真正平安的全方位SSO办理计划:Kerberos
我们的样例程序(桌面SSO和WEB-SSO)都有一个个性:要想将一个使用集成到我们的SSO办理计划中,或多或少的必要修正使用程序。Web使用必要设置一个我们预制的filter;桌面使用必要加上我们桌面SSO的JAAS模块(最少要修正JAAS的设置文件)。但是有良多程序是没有源代码和没法修正的,比方经常使用的远程通信程序telnet和ftp等等一些操纵体系本人带的经常使用的使用程序。这些程序是很难修正到场到我们的SSO的办理计划中。
现实上有一种全方位的SSO办理计划可以办理这些成绩,这就是Kerberos协定(RFC1510)。Kerberos是收集平安使用尺度(http://web.mit.edu/kerberos/),由MIT黉舍创造,被支流的操纵体系所接纳。在接纳kerberos的平台中,登录和认证是由操纵体系自己来保护,认证的凭据也由操纵体系来保留,如许全部桌面都能够处于统一个SSO的体系回护中。操纵体系中的各个使用(如ftp,telnet)只必要经由过程设置就可以到场到SSO中。别的利用Kerberos最年夜的优点在于它的平安性。经由过程密钥算法的包管和密钥中央的创建,能够做到用户的暗码基本不必要在收集中传输,而传输的信息也会非常的平安。
C++编译的是本地码,优点是启动快,而且可以精确控制资源因此可以开发很高效的程序.缺点是编程麻烦,而且容易留下安全隐患.跨平台靠源代码在各个平台间分别编译(一处编写到处编译) |
|