使用cookie实现跨域系统单点登录

来源:互联网 发布:社会网络分析大数据 编辑:程序博客网 时间:2024/05/24 01:26

 单点登录作为目前比较流行的服务于企业业务整合的解决方案之一, 使得在多个应用系统中,用户只需要 登录一次 就可以访问所有相互信任的应用系统。实现这一需求的思路和技术各有千秋.

一、SSO 的主要实现方式有:

1、   共享 cookies

基于共享同域的 cookie 是 Web 刚开始阶段时使用的一种方式,它利用浏览同域名之间自动传递 cookies 机制,实现两个域名之间系统令牌传递问题;另外,关于跨域问题,虽然 cookies本身不跨域,但可以利用它实现跨域的 SSO 。如:代理、暴露 SSO 令牌值等。

2、   Broker-based( 基于经纪人 )

这种技术的特点就是,有一个集中的认证和用户帐号管理的服务器。经纪人给被用于进一步请求的电子身份存取。中央数据库的使用减少了管理的代价,并为认证提供 一个公共和独立的 "第三方 " 。例如 Kerberos 、 Sesame 、 IBM KryptoKnight (凭证库思想 ) 等。 Kerberos是由麻省理工大学发明的安全认证服务,已经被 UNIX 和 Windows 作为 默认的安全认证服务集成进操作系统。

3、   Agent-based (基于代理人)

在这种解决方案中,有一个自动地为不同的应用程序认证用户身份的代理程序。这个代理程序需要设计有不同的功能。比如,它可以使用口令表或加密密钥来自动地将 认证的负担从用户移开。代理人被放在服务器上面,在服务器的认证系统和客户端认证方法之间充当一个 " 翻译 "。例如 SSH 等。

4、   Token-based

例如 SecureID,WebID ,现在被广泛使用的口令认证,比如 FTP 、邮件服务器的登录认证,这是一种简单易用的方式,实现一个口令在多种应用当中使用。

5、   基于网关

6、   基于 SAML

SAML(Security Assertion Markup Language ,安全断言标记语言)的出现大大简化了 SSO ,并被 OASIS 批准为 SSO 的执行标准 。开源组织 OpenSAML 实现了 SAML 规范。

 二、使用cookie实现跨域系统单点登录

  1. 同域下使用cookie实现SSO

    在上一篇博客中已经实现了使用cookie实现同域下SSO;主要思路是通过request请求获取表单提交的用户信息,验证令牌是否存在,不存在则生成令牌并把令牌信息存于cookie中,设置cookie的作用域(同域同路径),通过response把cookie信息返回表单,实现页面跳转。

  2. Cookie跨域访问

    同样,多域系统下,使用cookie实现SSO,cookie也是token令牌信息的承载体,所以cookie跨域实现SSO核心实则实现跨域读写cookie信息即可;在介绍具体方法之前,先简单介绍关于域和域名解析的过程:

    高并发负载均衡(一)——企业架构分析和DNS一文中已经详细介绍了关于域名基本概念。域名解析的过程:

    1、例如浏览器提交一个域名http://blog.csdn.net,接下来便在电脑本地的配置文件中查找是否存在该域名匹配的IP,如果有,直接获取到该域名匹配的ip,直接向该ip发送请求

    2、如果没有,在网络的

    由于设备有限,故直接通过修改该文件的方式虚拟两个域名。该文件即为sys32下host文件。添加127.0.0.1www.a.com 127.0.0.1 www.b.com两个域。

    下面介绍三种实现思路:

  1. 利用HTML script标签跨域写cookie

     利用HTML 的script标签主要是依赖于该标签的src属性,可支持访问任何域的资源,通过script发起一个get类型的网络请求,获取资源,例如引入js 等代码类同。

[html] view plain copy
  1. <title>将cookie写入其它域</title>  
  2. <!--   
  3.     当前域为www.a.com,  
  4.     下面的script标签是跨域写cookie的核心,  
  5.     通过此标签实现了向www.b.com域写入cookie  
  6.  -->  
  7. <script type="text/javascript" src="http://www.b.com/set_cookie?cname=token&cval=test123"></script>  
  8.    

这里通过src在www.a.com 域中访问b域的set_cookie方法,调用b域的controller实现将a域的cookie信息写入b域中。

[html] view plain copy
  1. /**  
  2.  * 将此servlet部署到等待cookie被写入的域中<br>  
  3.  * 例如:希望在test.loc域的页面中将cookie写入other.loc域中,则应将此servlet部署到other.loc域下  
  4.  */  
  5. @WebServlet("/set_cookie")  
  6. public class SetCookieServlet extends HttpServlet {  
  7.     private static final long serialVersionUID = 1L;  
  8.   
  9.     /**  
  10.      * 其它域通过页面script标签引用此servlet,script标签发起的请求是get类型,将实现写入doGet方法中  
  11.      */  
  12.     protected void doGet(HttpServletRequest request,  
  13.             HttpServletResponse response) throws ServletException, IOException {  
  14.         // 将要写入的cookie项,调用者通过参数传递  
  15.         String cookieName = request.getParameter("cname");  
  16.         String cookieVal = request.getParameter("cval");  
  17.   
  18.         // 生成cookie   
  19.         Cookie cookie = new Cookie(cookieName, cookieVal);  
  20.         cookie.setPath("/"); //www.a.com  
  21.         // 一般可以将domain设置到顶级域  
  22.         // cookie.setDomain("sub.a.com");   
  23.         response.addCookie(cookie);  
  24.     }  
  25.   
  26. }  

  1. P3P协议

      通过src属性跨域写cookie有浏览器限制,浏览器有一个隐私策略的限定,如果该浏览器支持这些安全保护,则使用第一种方法就行不通。所以当浏览器涉及第三方隐私时,跨域的数据写入可通过P3P协议进行配置,在被写入的域中,也就是www.b.com 中配置P3P,随着url一并返回到地址头部,以告知浏览器,当前允许a域写入cookie信息。

[html] view plain copy
  1. response.addHeader("P3P", "CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR");  

     3、通过URL参数实现跨域信息传递

     如果考虑到广泛的兼容性,可最直接的通过url参数传递的方式,重定向到b的url中,b域获取cookie信息,在该域中进行写入。这就只涉及到把a域的信息传递到b中,使用URL传参便可以实现。

[html] view plain copy
  1. @WebServlet("/tg")  
  2. public class TokenGeneratorServlet extends HttpServlet {  
  3.     private static final long serialVersionUID = 1L;  
  4.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  5.         // 请求的原始来源域  
  6.         String from  = request.getParameter("from");      
  7.         // 生成token  
  8.         String token = "test111";         
  9.         response.sendRedirect(from + "?cname=token&cval=" + token );  
  10.     }  
  11.   
  12. }  

    浏览器通过访问www.a.com/tg?from=http://www.b.com/set_cookie 访问tg servlet,重定向到b域的set_cookie方法,传入token参数.但如果有20多个系统需要sso,这样跳转可想而知。所以不建议使用这种方式

    SSO的实现思路有很多种,正如本文开篇所说,仅使用cookie的思路就各有不同,另外还包括一些当前已经封装好的技术专用于实现单点登录,条条大路通罗马,根据系统需求和项目实际情况选择较优方案即可。