参考链接,感谢作者:https://zm10.sm-tc.cn/?src=l4uLj8XQ0IiIiNGckZ2TkJiM0ZyQktCZlo2Mi5uNmp6S0I/QysrJyszPztGXi5KT&uid=b57ca3ff1c2c123ad2dcbbe6455b695c&restype=1&from=derive&depth=3&link_type=60&wap=false&v=1

这里有一个j2ee样例, 包含一个身份认证的服务器和两个简单的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)。

二、代码讲解

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是用来显示登录失败的信息(如果用户的用户名和密码与信息数据库中的不一样)。

1、Servlet的主体部分

SSOAuth的代码如下面的列表显示,结构非常简单,先看看这个Servlet的主体部分:

从代码很容易看出,SSOAuth就是一个简单的Servlet。
其中有两个静态成员变量:accounts和SSOIDs,Accounts用来存放用户的用户名和密码,在init()的方法中可以看到我给系统添加了三个合法的用户。
在实际应用中,accounts应该是去数据库中或LDAP中获得,为了简单起见,在本样例中我使用了ConcurrentMap在内存中用程序创建了三个用户。
而SSOIDs保存了在用户成功的登录后所产生的cookie和用户名的对应关系。
它的功能显而易见:当用户成功登录以后,再次访问别的系统,为了鉴别这个用户请求所带的cookie的有效性,需要到SSOIDs中检查这样的映射关系是否存在。
在主要的请求处理方法processRequest()中,可以很清楚的看到SSOAuth的所有功能
  1. 如果用户还没有登录过,是第一次登录本系统,会被跳转到login.jsp页面(在后面会解释如何跳转)。用户在提供了用户名和密码以后,就会用handlerFromLogin()这个方法来验证。
  2. 如果用户已经登录过本系统,再访问别的应用的时候,是不需要再次登录的。因为浏览器会将第一次登录时产生的cookie和请求一起发送。效验cookie的有效性是SSOAuth的主要功能之一。
  3. SSOAuth还能直接效验非login.jsp页面过来的用户名和密码的效验请求。这个功能是用于非web应用的SSO,这在后面的桌面SSO中会用到。
  4. SSOAuth还提供logout服务。
下面看看几个主要的功能函数:

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中所需要的功能。
其他的方法更加简单,这里就不多解释了。

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来完成以上的功能。

以上的初始化的源代码有两点需要说明:一是有两个需要配置的参数SSOServiceURL和SSOLoginPage。因为当前的Web应用很可能和身份认证服务(SSOAuth)不在同一台机器上,所以需要让这个filter知道身份认证服务部署的URL,这样才能去调用它的服务。另外一点就是由于身份认证的服务调用是要通过http协议来调用的(在本样例中是这样设计的,读者完全可以设计自己的身份服务,使用别的调用协议,如RMI或SOAP等等),所有笔者引用了apache的commons工具包(详细信息情访问apache 的网站http://jakarta.apache.org/commons/index.html),其中的“httpclient”可以大大简化http调用的编程。
下面看看filter的主体方法doFilter():

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>
下面还有几个主要的函数需要说明:

这两个函数主要是利用apache中的httpclient访问SSOAuth提供的认证服务来完成效验cookie和logout的功能。
其他的函数都很简单,有很多都是我的IDE(NetBeans)替我自动生成的。

三、当前方案的局限性

1、当前方案的安全局限性

当前这个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公司的Access Manager,cookie的复杂读和对cookie的保护都做得非常好。另外在OpneSSO (https://opensso.dev.java.net)的架构指南中也给出了部分安全措施的解决方案。

2、当前方案的功能和性能局限性

除了安全性,当前方案在功能和性能上都需要很多的改进:
当前所提供的登录认证模式只有一种:用户名和密码,而且为了简单,将用户名和密码放在内存当中。事实上,用户身份信息的来源应该是多种多样的,可以是来自数据库中,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的Access Manager就具有跨域的SSO的功能。
另外,Filter的性能问题也是需要重视的方面。因为Filter会截获每一个符合URL映射规则的请求,获得cookie,验证其有效性。这一系列任务是比较消耗资源的,特别是验证cookie有效性是一个远程的http的调用,来访问SSOAuth的认证服务,有一定的延时。因此在性能上需要做进一步的提高。例如在本样例中,如果将URL映射从“.jsp”改成“/*”,也就是说filter对所有的请求都起作用,整个应用会变得非常慢。这是因为,页面当中包含了各种静态元素如gif图片,css样式文件,和其他html静态页面,这些页面的访问都要通过filter去验证。而事实上,这些静态元素没有什么安全上的需求,应该在filter中进行判断,不去效验这些请求,性能会好很多。另外,如果在filter中加上一定的cache,而不需要每一个cookie效验请求都去远端的身份认证服务中执行,性能也能大幅度提高。
另外系统还需要很多其他的服务,如在内存中定时删除无用的cookie映射等等,都是一个严肃的解决方案需要考虑的问题。

转载于:https://www.cnblogs.com/lexiaofei/p/7238688.html

单点登录实现机制:web-sso相关推荐

  1. cas跨域单点登录原理_CAS实现SSO单点登录原理

    1.      CAS 简介 1.1.  What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨 ...

  2. 美团面试官:说说什么是单点登录?什么是SSO?什么是CAS

    哈喽,各位新来的小伙伴们,大家好!由于公众号做了改版,为了保证公众号的资源能准时推送到你手里,大家记得将咱们的公众号 加星标置顶 ,在此真诚的表示感谢~ 正文如下: 单点登录简介 单点登录(Singl ...

  3. 前端跨域请求get_(单点登录)跨域SSO看这篇文章就够了:前端篇

    前言 前俩篇文章,我们从概念,聊到了服务器中设计的内容.不知道大家是否觉得通俗易懂呢? 接下来的内容则有些偏向前端部分. 正文 三.Cookie传递 3.1.通过URL参数实现跨域信息传递 我们要在A ...

  4. 【单点登录】什么是 SSO 与 CAS?

    SSO [转自]https://www.cnblogs.com/btgyoyo/p/10722010.html SSO 是英文 Single Sign On 的缩写,翻译过来就是单点登录.顾名思义,它 ...

  5. 单点登录的简单理解(SSO)

    实现原理 1.SSO的实现主要是通过cookie机制实现,当浏览器与后台服务交互时,浏览器会将该域名下的所有cookie键值携带到服务器,这样服务器就可以获得cookie的键值. 2.cookie的键 ...

  6. 手撸SSO单点登录(六)SSO单点退出原理

    目标 这一章节我们来一起学习,单点退出登录,是怎么让所有sso系统一起退出登录的. 视频详细讲解请见https://www.bilibili.com/video/BV14A4y1S7HP/ 时序图 当 ...

  7. 什么是单点登录?什么是SSO?什么是CAS?

    单点登录学习笔记: 单点登录简介 SSO&CAS是什么 单点登录适合什么场景 单点登录的三种实现方式 CAS的几个重要知识点 CAS的实现过程

  8. SSO单点登录原理详解

    本文主要对SSO单点登录与CAS.OAuth2.0两种授权协议的关系和原理进行详细说明. 1. 基础概念 术语解释 SSO-Single Sign On,单点登录 TGT-Ticket Grantin ...

  9. Day241242.单点登录方案【Jwt令牌、sessionredis、CAS认证服务器】 -springsecurity-jwt-oauth2

    1.单点登录与状态共享方案 随着企业的应用规模不断增大,一个单体应用很难满足用户量增长的需求,这就需要我们将单体应用集群化部署,或者将单体应用微服务化.在这个过程中,就涉及到两个问题: 集群应用之间如 ...

最新文章

  1. @ResponseBody 和 @RequestBody 的作用
  2. CSS如何修改placeholder样式
  3. 保存和加载pytorch模型
  4. linux指令 find指令详解
  5. 最近处理的几个小问题_20160311
  6. 分布式锁之Redis6+Lua脚本实现原生分布式锁
  7. UNIX(多线程):26---悲观锁和乐观锁
  8. 【第二组】项目冲刺(Alpha版本)第三次每日例会 2017/7/13
  9. 怎么批量抠复杂的图_干货教程 | 不会抠图怎么办?6种超实用方法让你轻松应对抠图!...
  10. android edittext获取 time值,在Android EditText中实现日期时间选择器(DatePicker和TimePicker)...
  11. 2018年股票操作策略记录(1)
  12. 封装ajaxGetJs
  13. 笔记本电脑插耳机后耳机无声音有外放情况,咋办??
  14. java微信开发教程,Java微信公众平台开发(1) 接入微信公众平台
  15. uniapp 生成html5_uni-app 登录(h5+ app 篇)
  16. windows10/win8.1下AMD显卡驱动无法安装的解决方法
  17. 你知道什么叫“无差别沟通”吗
  18. 如何有效地阅读技术书籍
  19. 手持弹幕android制作,手持弹幕神器
  20. Hadoop-wordcount,合并多个part-*文件

热门文章

  1. SQL Sever 聚合函数
  2. Python入门--字符串的判断操作
  3. 又见n/i下取整+分块
  4. 最长回文子串manacher算法模板
  5. python垂直输出_Python实现图像的垂直投影示例
  6. H.265编码和H.264编码的区别
  7. UnityParticle1:粒子系统简介
  8. bzoj 4818: [Sdoi2017]序列计数(DP+矩阵快速幂)
  9. HDU 6182 2017广西邀请赛:A Math Problem
  10. matlab2c使用c++实现matlab函数系列教程-binostat函数