[转]编写你自己的单点登录(SSO)服务 3

上一篇 / 下一篇  2008-02-15 11:46:10 / 个人分类:SSO

来源:http://developers.sun.com.cn/blog/yutoujava/entry/200704132

6桌面SSO的实现

WEB-SSO概念延伸开,我们可以把SSO的技术拓展到整个桌面的应用,不仅仅局限在浏览器。SSO的概念和原则都没有改变,只需要再做一点点的工作,就可以完成桌面SSO的应用。

桌面SSOWEB-SSO一样,关键的技术也在于如何在用户登录过后保存登录的凭据。在WEB-SSO中,登录的凭据是靠浏览器的cookie机制来完成的;在桌面应用中,可以将登录的凭证保存到任何地方,只要所有SSO的桌面应用都共享这个凭证。

从网站可以下载一个简单的桌面SSO的样例(http://gceclub.sun.com.cn/wangyu/desktop-sso/desktopsso.zip)和全部源码(http://211.151.94.21/blog/yutoujava/resource/desktopsso_src.zip),虽然简单,但是它具有桌面SSO大多数的功能,稍微加以扩充就可以成为自己的解决方案。



    6.1桌面样例的部署

  1. 运行此桌面SSO需要三个前提条件:
    a) WEB-SSO
    的身份认证应用应该正在运行,因为我们在桌面SSO当中需要用到统一的认证服务
    b)
    当前桌面需要运行MozillaNetscape浏览器,因为我们将ticket保存到mozillacookie文件中
    c)
    必须在JDK1.4以上运行。(WEB-SSO需要JDK1.5以上)

  2. 解开desktopsso.zip文件,里面有两个目录binlib

  3. bin目录下有一些脚本文件和配置文件,其中config.properties包含了三个需要配置的参数:
    a) SSOServiceURL
    要指向WebSSO部署的身份认证的URL
    b) SSOLoginPage
    要指向WebSSO部署的身份认证的登录页面URL
    c) cookiefilepath
    要指向当前用户的mozilla所存放cookie的文件

  4. bin目录下还有一个login.conf是用来配置JAAS登录模块,本样例提供了两个,读者可以任意选择其中一个(也可以都选),再重新运行程序,查看登录认证的变化

  5. bin下的运行脚本可能需要作相应的修改
    a)
    如果是在unix下,各个jar文件需要用“:”来隔开,而不是“;”
    b) java
    运行程序需要放置在当前运行的路径下,否则需要加上java的路径全名。



    6.2桌面样例的运行

样例程序包含三个简单的Java控制台程序,这三个程序单独运行都需要登录。如果运行第一个命叫“GameSystem”的程序,提示需要输入用户名和密码:



效验成功以后,便会显示当前登录的用户的基本信息等等。





这时候再运行第二个桌面Java应用(mailSystem)的时候,就不需要再登录了,直接就显示出来刚才登录的用户。



第三个应用是logout,运行它之后,用户便退出系统。再访问的时候,又需要重新登录了。请读者再制裁执行完logout之后,重新验证一下前两个应用的SSO:先运行第二个应用,再运行第一个,会看到相同的效果。

我们的样例并没有在这里停步,事实上,本样例不仅能够和在几个Java应用之间SSO,还能和浏览器进行SSO,也就是将浏览器也当成是桌面的一部分。这对一些行业有着不小的吸引力。

这时候再打开Mozilla浏览器,访问以前提到的那两个WEB应用,会发现只要桌面应用如果登录过,Web应用就不用再登录了,而且能显示刚才登录的用户的信息。读者可以在几个桌面和Web应用之间进行登录和logout的试验,看看它们之间的SSO



    6.3桌面样例的源码分析

    桌面SSO的样例使用了JAAS(要了解JAAS的详细的信息请参考http://java.sun.com/products/jaas)。JAAS是对PAMPluggable Authentication Module)的Java实现,来完成Java应用可插拔的安全认证模块。使用JAAS作为Java应用的安全认证模块有很多好处,最主要的是不需要修改源代码就可以更换认证方式。例如原有的Java应用如果使用JAAS的认证,如果需要应用SSO,只需要修改JAAS的配置文件就行了。现在在流行的J2EE和其他Java的产品中,用户的身份认证都是通过JAAS来完成的。在样例中,我们就展示了这个功能。请看配置文件login.conf

DesktopSSO {desktopsso.share.PasswordLoginModule required;desktopsso.share.DesktopSSOLoginModule required;};

当我们注解掉第二个模块的时候,只有第一个模块起作用。在这个模块的作用下,只有test用户(密码是12345)才能登录。当我们注解掉第一个模块的时候,只有第二个模块起作用,桌面SSO才会起作用。



所有的Java桌面样例程序都是标准JAAS应用,熟悉JAAS的程序员会很快了解。JAAS中主要的是登录模块(LoginModule)。下面是SSO登录模块的源码:

public class DesktopSSOLoginModule implements LoginModule {..........private String SSOServiceURL = "";private String SSOLoginPage = "";private static String cookiefilepath = "";.........


config.properties的文件中,我们配置了它们的值:

SSOServiceURL=http://wangyu.prc.sun.com:8080/SSOAuth/SSOAuthSSOLoginPage=http://wangyu.prc.sun.com:8080/SSOAuth/login.jspcookiefilepath=C:\\Documents and Settings\\yw137672\\Application Data\\Mozilla\\Profiles\\default\\hog6z1ji.slt\\cookies.txt

SSOServiceURLSSOLoginPage成员变量指向了在Web-SSO中用过的身份认证模块:SSOAuth,这就说明在桌面系统中我们试图和Web应用共用一个认证服务。而cookiefilepath成员变量则泄露了一个“天机”:我们使用了Mozilla浏览器的cookie文件来保存登录的凭证。换句话说,和Mozilla共用了一个保存登录凭证的机制。之所以用Mozilla是应为它的Cookie文件格式简单,很容易编程访问和修改任意的Cookie值。(我试图解析Internet Explorercookie文件但没有成功。)

下面是登录模块DesktopSSOLoginModule的主体:login()方法。逻辑也是非常简单:先用Cookie来登陆,如果成功,则直接就进入系统,否则需要用户输入用户名和密码来登录系统。

public boolean login() throws LoginException{try {if (Cookielogin()) return true;} catch (IOException ex) {ex.printStackTrace();}if (passwordlogin()) return true;throw new FailedLoginException();}



下面是Cookielogin()方法的实体,它的逻辑是:先从Cookie文件中获得相应的Cookie值,通过身份效验服务效验Cookie的有效性。如果cookie有效就算登录成功;如果不成功或Cookie不存在,用cookie登录就算失败。

public boolean Cookielogin() throws LoginException,IOException {String  cookieValue="";int cookieIndex =foundCookie();if (cookieIndex<0)return false;elsecookieValue = getCookieValue(cookieIndex);username = cookieAuth(cookieValue);if (! username.equals("failed")) {loginSuccess =  true;return true;}return false;}





用用户名和密码登录的方法要复杂一些,通过Callback的机制和屏幕输入输出进行信息交互,完成用户登录信息的获取;获取信息以后通过userAuth方法来调用远端SSOAuth的服务来判定当前登录的有效性。

public boolean passwordlogin() throws LoginException {//// Since we need input from a user, we need a callback handlerif (callbackHandler == null) {throw new LoginException("No CallbackHandler defined");}Callback[] callbacks = new Callback[2];callbacks[0] = new NameCallback("Username");callbacks[1] = new PasswordCallback("Password", false);//// Call the callback handler to get the username and passwordtry {callbackHandler.handle(callbacks);username = ((NameCallback)callbacks[0]).getName();char[] temp = ((PasswordCallback)callbacks[1]).getPassword();password = new char[temp.length];System.arraycopy(temp, 0, password, 0, temp.length);((PasswordCallback)callbacks[1]).clearPassword();} catch (IOException ioe) {throw new LoginException(ioe.toString());} catch (UnsupportedCallbackException uce) {throw new LoginException(uce.toString());}System.out.println();String authresult ="";try {authresult = userAuth(username, password);} catch (IOException ex) {ex.printStackTrace();}if (! authresult.equals("failed")) {loginSuccess= true;clearPassword();try {updateCookie(authresult);} catch (IOException ex) {ex.printStackTrace();}return true;}loginSuccess = false;username = null;clearPassword();System.out.println( "Login: PasswordLoginModule FAIL" );throw new FailedLoginException();}



CookieAuthuserAuth方法都是利用apahcehttpclient工具包和远程的SSOAuth进行http连接,获取服务。

private String cookieAuth(String cookievalue) throws IOException{String result = "failed";HttpClient httpclient = new HttpClient();GetMethod httpget = new GetMethod(SSOServiceURL+Action1+cookievalue);try {httpclient.executeMethod(httpget);result = httpget.getResponseBodyAsString();} finally {httpget.releaseConnection();}return result;}private String userAuth(String username, char[] password) throws IOException{String result = "failed";String passwd= new String(password);HttpClient httpclient = new HttpClient();GetMethod httpget = new GetMethod(SSOServiceURL+Action2+username+"&password="+passwd);passwd = null;try {httpclient.executeMethod(httpget);result = httpget.getResponseBodyAsString();} finally {httpget.releaseConnection();}return result;}



还有一个地方需要补充说明的是,在本样例中,用户名和密码的输入都会在屏幕上显示明文。如果希望用掩码形式来显示密码,以提高安全性,请参考:http://java.sun.com/developer/technicalArticles/Security/pwordmask/

7真正安全的全方位SSO解决方案:Kerberos

我们的样例程序(桌面SSOWEB-SSO)都有一个共性:要想将一个应用集成到我们的SSO解决方案中,或多或少的需要修改应用程序。Web应用需要配置一个我们预制的filter;桌面应用需要加上我们桌面SSOJAAS模块(至少要修改JAAS的配置文件)。可是有很多程序是没有源代码和无法修改的,例如常用的远程通讯程序telnetftp等等一些操作系统自己带的常用的应用程序。这些程序是很难修改加入到我们的SSO的解决方案中。

事实上有一种全方位的SSO解决方案能够解决这些问题,这就是Kerberos协议(RFC 1510)。Kerberos是网络安全应用标准(http://web.mit.edu/kerberos/),由MIT学校发明,被主流的操作系统所采用。在采用kerberos的平台中,登录和认证是由操作系统本身来维护,认证的凭证也由操作系统来保存,这样整个桌面都可以处于同一个SSO的系统保护中。操作系统中的各个应用(如ftp,telnet)只需要通过配置就能加入到SSO中。另外使用Kerberos最大的好处在于它的安全性。通过密钥算法的保证和密钥中心的建立,可以做到用户的密码根本不需要在网络中传输,而传输的信息也会十分的安全。

目前支持Kerberos的操作系统包括Solaris, windows,Linux等等主流的平台。只不过要搭建一个Kerberos的环境比较复杂,KDC(密钥分发中心)的建立也需要相当的步骤。Kerberos拥有非常成熟的API,包括JavaAPI。使用Java Generic Security Services(GSS) API并且使用JAAS中对Kerberos的支持(详细信息请参见SunJava&Kerberos教程http://java.sun.com/ j2se/1.5.0/docs/guide/security/jgss/tutorials/index.html),要将我们这个样例改造成对Kerberos的支持也是不难的。值得一提的是在JDK6.0http://www.java.net/download/jdk6)当中直接就包含了对GSS的支持,不需要单独下载GSS的包。



8总结

本文的主要目的是阐述SSO的基本原理,并提供了一种实现的方式。通过对源代码的分析来掌握开发SSO服务的技术要点和充分理解SSO的应用范围。但是,本文仅仅说明了身份认证的服务,而另外一个和身份认证密不可分的服务----权限效验,却没有提到。要开发出真正的SSO的产品,在功能上、性能上和安全上都必须有更加完备的考虑。

附件:

作者简介

王昱是Sun中国工程研究院的Java工程师,现在的主要负责全球合作伙伴的技术支持。作为一名Java资深工程师和架构师,王昱在Java的很多领域都有多年的造诣,特别是在Java虚拟机、J2EE技术(包括EJB, JSP/Servlet, JMSWeb services等技术)、集群技术和Java应用性能调优上有着较为丰富的经验。曾经多次在重要的Java会议发表演讲,并在国际著名的Java技术站点发表文章。



资源链接


TAG: sso 单点登录 单点登录服务

引用 删除 Guest   /   2008-03-07 17:45:40
money大哥,能给我发一份源码吗?谢谢!我的邮箱是:peiyapy@sina.com
引用 删除 Guest   /   2008-03-07 17:44:26
演示的源代码怎么下载不了呢?
哪位大哥可以给我发一份呢,
因为最近公司让我做几个web(B/S)系统和1个C/S系统的单点登录,想看看您的代码,但下载不了,请您能在百忙之中能发给我您的源代码(SSOAuth.zip、SSOWebDemo1.zip、SSOWebDemo2.zip),我的邮箱是:peiyapy@sina.com,万分感谢!!!
静·谧 引用 删除 lastwinner   /   2008-03-05 14:32:38
文章我是转载的,并未深入了解,请直接咨询原作者
引用 删除 money   /   2008-02-28 15:21:39
请问如何修改“domainname”的属性以反映实际的应用部署情况
如何修改其中的几个初始化参数
<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)以反映实际的部署情况

我直接打开这些文件
没看到domainname等
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-05-17  
    123
45678910
11121314151617
18192021222324
25262728293031

数据统计

  • 访问量: 2836
  • 日志数: 40
  • 建立时间: 2007-12-12
  • 更新时间: 2008-05-14

RSS订阅

Open Toolbar