`
phosphory
  • 浏览: 72746 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类

SSO单点登录解决方案讨论三(转载自百洋软件研究实验)

阅读更多

文章出自于: 百洋软件研究实验室博客  http://www.po-soft.com

 3 WEB-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,浏览器就会向Web Server去发送请求。如下图,浏览器向Web服务器发送了两个请求,申请了两个页面。这两个页面的请求是分别使用了两个单独的HTTP连接。所谓无状 态的协议也就是表现在这里,浏览器和Web服务器会在第一个请求完成以后关闭连接通道,在第二个请求的时候重新建立连接。Web服务器并不区分哪个请求来 自哪个客户端,对所有的请求都一视同仁,都是单独的连接。这样的方式大大区别于传统的(Client/Server)C/S结构,在那样的应用中,客户端 和服务器端会建立一个长时间的专用的连接通道。正是因为有了无状态的特性,每个连接资源能够很快被其他客户端所重用,一台Web服务器才能够同时服务于成 千上万的客户端。
 
      但是我们通常的应用是有状态的。先不用提不同应用之间的SSO,在同一个应用中也需要保存用户的登录身份信息。例如用户在访问页面1的时候进行了登录,但 是刚才也提到,客户端的每个请求都是单独的连接,当客户再次访问页面2的时候,如何才能告诉Web服务器,客户刚才已经登录过了呢?浏览器和服务器之间有 约定:通过使用cookie技术来维护应用的状态。Cookie是可以被Web服务器设置的字符串,并且可以保存在浏览器中。如下图所示,当浏览器访问了 页面1时,web服务器设置了一个cookie,并将这个cookie和页面1一起返回给浏览器,浏览器接到cookie之后,就会保存起来,在它访问页 面2的时候会把这个cookie也带上,Web服务器接到请求时也能读出cookie的值,根据cookie值的内容就可以判断和恢复一些用户的信息状 态。
 
      Web-SSO完全可以利用Cookie结束来完成用户登录信息的保存,将浏览器中的Cookie和上文中的Ticket结合起来,完成SSO的功能。

      为了完成一个简单的SSO的功能,需要两个部分的合作:

  • 统一的身份认证服务。
  • 修改Web应用,使得每个应用都通过这个统一的认证服务来进行身份效验。


   3.1 Web SSO 的样例
      根据上面的原理,我用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,Sun Application Server 8, Jboss 4等)。另外,身份认证服务需要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 -cvf SSOAuth.war SSOAuth/”就可以完成这个功能。
  • 解压缩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 -cvf SSOWebDemo1.war SSOWebDemo1/”就可以完成这个功能。
  • 请输入第一个web应用的测试URL(test.jsp),例如http://wangyu.prc.sun.com:8080/SSOWebDemo1/test.jsp,如果是第一次访问,便会自动跳转到登录界面,如下图。


  • 使用系统自带的三个帐号之一登录(例如,用户名:wangyu,密码:wangyu),便能成功的看到test.jsp的内容:显示当前用户名和欢迎信息。


  • 请接着在同一个浏览器中输入第二个web应用的测试URL(test.jsp),例如http://wangyu.prc.sun.com:8080/SSOWebDemo2/test.jsp。你会发现,不需要再次登录就能看到test.jsp的内容,同样是显示当前用户名和欢迎信息,而且欢迎信息中明确的显示当前的应用名称(demo2)。   



   3.2 WEB-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的主体部分:
package DesktopSSO;

import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;

import javax.servlet.*;
import javax.servlet.http.*;


public class SSOAuth extends HttpServlet {
    
      static private ConcurrentMap accounts;
      static private ConcurrentMap SSOIDs;
      String cookiename="WangYuDesktopSSOID";
      String domainname;
    
      public void init(ServletConfig config) throws ServletException {
          super.init(config);
          domainname= config.getInitParameter("domainname");
          cookiename = config.getInitParameter("cookiename");
          SSOIDs = new ConcurrentHashMap();
          accounts=new ConcurrentHashMap();
          accounts.put("wangyu", "wangyu");
          accounts.put("paul", "paul");
          accounts.put("carol", "carol");
      }

      protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          PrintWriter ut = response.getWriter();
          String action = request.getParameter("action");
          String result="failed";
          if (action==null) {
              handlerFromLogin(request,response);
          } else if (action.equals("authcookie")){
              String myCookie = request.getParameter("cookiename");
              if (myCookie != null) result = authCookie(myCookie);
              out.print(result);
              out.close();
          } else if (action.equals("authuser")) {
             result=authNameAndPasswd(request,response);
              out.print(result);
              out.close();
          } else if (action.equals("logout")) {
              String myCookie = 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服务。   


      下面看看几个主要的功能函数:
private void handlerFromLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          String username = request.getParameter("username");
          String password = request.getParameter("password");
          String pass = (String)accounts.get(username);
          if ((pass==null)||(!pass.equals(password)))
              getServletContext().getRequestDispatcher("/failed.html").forward(request, response);
          else {
              String gotoURL = request.getParameter("goto");
              String newID = createUID();
              SSOIDs.put(newID, username);
              Cookie wangyu = new Cookie(cookiename, newID);
              wangyu.setDomain(domainname);
              wangyu.setMaxAge(60000);
              wangyu.setValue(newID);
              wangyu.setPath("/");
              response.addCookie(wangyu);
              System.out.println("login success, goto back url:" + gotoURL);
              if (gotoURL != null) {
                  PrintWriter ut = 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应用来调用的。
文章出自于: 百洋软件研究实验室博客  http://www.po-soft.com

分享到:
评论

相关推荐

    SSO单点登录解决方案

    ### SSO单点登录解决方案详解 #### 一、单点登录概述 单点登录(Single Sign-On,简称SSO)是一种先进的解决方案,旨在通过让用户仅需登录一次即可访问所有相互信任的应用系统,从而提高用户体验并简化安全管理。...

    SSO 单点登录解决方案 设计流程图

    SSO 单点登录解决方案 设计流程图 SSO(Single Sign-On)单点登录解决方案是当前企业应用系统中最常用的身份验证机制之一。该解决方案的设计流程图将会详细介绍 SSO 的实现机制、时序图、数据库设计、程序实现和...

    SSO单点登陆解决方案

    SSO单点登录解决方案 SSO(Single Sign-On)单点登录解决方案旨在提供一个统一的身份验证入口,满足集团多个成员网站的身份验证需求。该方案的主要目标是实现单点登录,提高用户体验,降低成员网站的登录负载,并...

    sso单点登录ppt.ppt

    sso单点登录ppt.ppt

    统一认证单点登录系统SSO解决方案.doc

    单点登录(Single Sign-On,简称SSO)是一种网络...综上所述,统一认证单点登录系统SSO解决方案是一种高效、安全、灵活的方法,能够有效应对企业环境中多系统登录的挑战,提升用户满意度,同时便于系统的管理和扩展。

    cas 单点登录 解决方案.

    cas 单点登录解决方案 cas 单点登录解决方案是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。随着企业的发展,业务系统的数量...

    SSO单点登录

    SSO单点登录

    SSO单点登录解决方案.doc

    SSO(Single Sign-On)单点登录是一种身份验证机制,允许...总的来说,SSO单点登录解决方案是现代企业IT环境中必不可少的组件,它提升了用户便利性,降低了管理成本,加强了安全性,并适应了SOA环境下的服务安全需求。

    PHP 使用TP5.0 实现SSO单点登录

    因为公司要实现SSO单点登录的效果,最近在网上找了一些资料,但是都没有好用的, 所以自己用PHP 使用TP5.0 实现了SSO单点登录,可以跨多个域名。 下载后在本地配置好 A,B,C 3个网站,就可以模拟效果了。

    关于SSO单点登录的简单实现

    SSO(Single Sign-On)单点登录是一种身份验证机制,允许用户在一次登录后访问多个相互关联的应用系统,而无需再次进行身份验证。这个过程提高了用户体验,同时也简化了安全管理。在本文中,我们将探讨SSO的基本原理...

    单点登录SSO解决方案之SpringSecurity+JWT实现.docx

    ### 单点登录SSO解决方案之SpringSecurity+JWT实现 #### 一、单点登录(SSO)概述 单点登录(Single Sign-On,简称SSO)是一种认证机制,允许用户仅通过一次登录就能访问同一域下的多个应用程序和服务。这种机制...

    sso单点登录

    单点登录(Single Sign-On,简称SSO)是一种网络访问控制机制,允许用户在一次登录后,无需再次认证即可访问多个相互信任的应用系统。这种方式极大地提高了用户体验,减少了用户记忆和输入多个账号密码的麻烦,同时...

Global site tag (gtag.js) - Google Analytics