累积:技海拾贝――基于反向代理的单点登录方案

累积:技海拾贝――基于反向代理的单点登录方案
累积:技海拾贝――基于反向代理的单点登录方案

累积:技海拾贝|Cumulation

基于反向代理的单点登录方案

文:电力事业部 王雁飞

1. 概述

实现单点登录要解决问题是:用户体验到只需一次登录就能以适当的用户身份访问多个相关应用系统。单点登录方案的核心是统一身份认证和统一用户身份管理。

在企业范围内建立统一的身份管理系统,一般采用标准的目录服务实现认证和身份数据存储。通过建立统一的帐户存储和管理中心,作为所有账号管理行为的数据存储,以自动化的,基于策略的方式实现帐户的创建,变更,销户。

如果各个应用系统和统一身份管理系统帐户没有统一,统一身份管理系统还负责各个系统帐户在其他多个应用系统中映射帐户管理。当在统一身份管理系统创建用户,用户信息保存到目录服务器,同时在此用户将要访问的其他应用系统中建立他的相应帐户,或者直接映射一个已经存在用户。当用户信息修改,也要同步到其他应用系统中。当从统一身份管理系统删除用户,用户信息从目录服务器删除,同时在此用户将要访问的其他应用系统中删除他的相应帐户。

如果各个业务应用系统可以识别相同的登录用户身份标识,就不必做用户身份在各个应用系统的同步维护管理工作。

电力营销业务应用基于J2EE技术路线开发,由多个业务模块组成,每个业务模块部署为一个Web Module。用户通过同一登录入口进入系统,在同一浏览器窗口可以访问到多个业务模块的资源。本文介绍了多个应用模块之间单点登录方案和实现情况。

2. 背景知识

2.1. Http Cookie特性

2.1.1. 概述

Cookie是通过Http 会话头部分传递的文本信息。Cookie有名字Name、值Value、域Domain、路径Path等属性组成。

Cookie用于在Http这个无状态的协议下实现服务器和客户端的会话,使得服务器可以“识别”特定的客户端会话。Cookie在Http服务器响应客户端浏览器请求时生成发送给浏

览器。如下面是一个Http响应的例子。注意:在实际的Http通信过程中下面内容的每行结束是连续两个回车符(ASCII码13):

注意:下面例子的HTTP 会话是通过 TCPTrace

(https://www.360docs.net/doc/1a13218214.html,/tcptrace/)工具记录。

HTTP/1.1 200 OK

ETag: W/"995-1180415860109"

Last-Modified: Tue, 29 May 2007 05:17:40 GMT

Content-Type: text/html

Content-Length: 995

Date: Fri, 22 Jun 2007 05:21:51 GMT

Server: Apache-Coyote/1.1

Set-Cookie: JSESSIONID=AD62C0D503D40E0E6E7CE50FA1D1D45F; Path=/testweb

Set-Cookie: currentAppContextCookie=testweb; Path=/testweb

Set-Cookie 用来说明Cookie。

JSESSIONID 是名字。JSESSIONID 是J2EE应用服务器缺省使用的特定的名字,标识HttpSession的ID。

浏览器把Cookie暂存在内存或者文件中。当浏览器后续发送请求到服务器时会把Cookie回送服务器。如下面的Http 请求的例子:

GET /testweb/session/session.jsp?name=cmp_test&event=show HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*

Referer: http://localhost:8888/epsa/

Accept-Language: zh-cn,en-us;q=0.5

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Host: localhost:8888

Connection: Keep-Alive

Cookie:currentAppContextCookie=testweb;

JSESSIONID=AD62C0D503D40E0E6E7CE50FA1D1D45F;

服务器根据识别特定的Cookie就可以“识别”客户端。通过Cookie,Http服务器和客户端浏览器之间多次无状态的请求、响应过程就可以变得前后有联系了,就好像是有状态了的会话过程了。

浏览器回送Cookie时也是有一定约束的。浏览器可能在内存中和文件中保存了很多Cookie,但它不会把所有Cookie不加区别的全部发送给服务器。浏览器会匹配Cookie的Path属性值和目标URL,能匹配上的才会通过Http请求头发送给服务器。Cookie Path 一般是URL的一部分。如请求URL为:

http://localhost:8888/testweb/session/session.jsp

返回的 Cookie 的Path可以是“/testweb”,或者“/testweb/session”,但不应该是“/testapp”等“超出”了当前请求URL的路径。这样的Cookie传送到客户端时浏览器也会被保存,但是因为和后续对 /testweb 的请求URL不匹配,它们不会被回送到服务器。如果此时访问:http://localhost:8888/testapp/session/session.jsp,这个Cookie 才能被回送。

上面的讨论只关注了 Path 属性,还要考虑Domain属性。必须是Path属性和Domain 属性同时能匹配要请求的URL,Cookie才能被回送到服务器。

2.1.2. 试验过程

下面是一个完整的试验过程。

在 http://localhost:8888/testapp/session/session.jsp 中如下代码:

Cookie cookieRoot = new Cookie("cookieRoot", "cookieRoot");

Cookie cookieApp = new Cookie("cookieApp", "cookieApp");

Cookie cookieA = new Cookie("cookieA", "AAAAAA");

Cookie cookieB = new Cookie("cookieB", "BBBBBB");

cookieRoot.setPath("/");

cookieApp.setPath(request.getContextPath());

cookieA.setPath("/appA");

cookieB.setPath("/appB");

response.addCookie(cookieRoot);

response.addCookie(cookieApp);

response.addCookie(cookieA);

response.addCookie(cookieB);

通过浏览器访问,发出Http 请求:

POST /testweb/session/session.jsp HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*

Referer: http://localhost:8888/testweb/session/session.jsp

Accept-Language: zh-cn,en-us;q=0.5

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Host: localhost:8888

Content-Length: 42

Connection: Keep-Alive

Cache-Control: no-cache

Cookie:JSESSIONID=9F34C567EB5A00549E53295BD8A20283;

Http 响应:

HTTP/1.1 200 OK

Set-Cookie: cookieRoot=cookieRoot; Path=/

Set-Cookie: cookieApp=cookieApp; Path=/testweb

Set-Cookie: cookieA=AAAAAA; Path=/appA

Set-Cookie: cookieB=BBBBBB; Path=/appB

Content-Type: text/html;charset=ISO-8859-1

Content-Length: 5151

Date: Fri, 22 Jun 2007 09:05:53 GMT

Server: Apache-Coyote/1.1

此时浏览器收到了4个Cookie,它们的Path各不相同。继续下面试验。

Http 请求:

POST /testweb/session/session.jsp HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*

Referer: http://localhost:8888/testweb/session/session.jsp

Accept-Language: zh-cn,en-us;q=0.5

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Host: localhost:8888

Content-Length: 42

Connection: Keep-Alive

Cache-Control: no-cache

Cookie: JSESSIONID=9F34C567EB5A00549E53295BD8A20283; cookieApp=testweb; cookieRoot=cookieRoot;

可以看到,浏览器回送Path=/testweb 的Cookie和Path=/ 的 Cookie。

Http 请求:

GET /appA HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*

Accept-Language: zh-cn,en-us;q=0.5

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Host: localhost:8888

Connection: Keep-Alive

Cookie: cookieA=AAAAAA; cookieRoot=cookieRoot;

可以看到,浏览器回送了 Path=/appA 的Cookie和Path=/ 的 Cookie。

注意:当访URL为“/”时,“/”的子目录路径的Cookie 也回送了。

Http 请求:

GET /appB HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*

Accept-Language: zh-cn,en-us;q=0.5

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Host: localhost:8888

Connection: Keep-Alive

Cookie: cookieB=BBBBBB; cookieRoot=cookieRoot;

可以看到,浏览器回送了 Path=/appB 的Cookie和Path=/ 的 Cookie。

注意:当访URL为“/”时,“/”的子目录路径的Cookie 也回送了。

Http 请求:

GET / HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*

Accept-Language: zh-cn,en-us;q=0.5

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Host: localhost:8888

Connection: Keep-Alive

可以看到,浏览器回送了 Path=/ 的 Cookie。

再修改请求的服务器地址:

http://192.168.220.96:8888/testweb/session/session.jsp

可以看到,浏览器没有回送上述Cookie中任何一个。

2.1.

3. 小结

Cookie是否回送规则可以概括为:Cookie的Domain和Path必须匹配请求的URL。

Cookie的Path一般设置为访问该Web应用的上下文的根目录。

2.1.4. JSESSIONID Cookie

JSESSIONID是会话Cookie,当浏览器第一次访问J2EE Web应用,应用服务器会立即设置该Cookie,标识一个新的会话。如下例当访问http://localhost:8888/testapp,Http 响应:

HTTP/1.1 200 OK

Set-Cookie: JSESSIONID=F04DD75030A19C22110C14402A964C2F; Path=/testweb

Content-Type: text/html;charset=ISO-8859-1

Content-Length: 5151

Date: Fri, 22 Jun 2007 09:10:59 GMT

Server: Apache-Coyote/1.1

对于客户端浏览器来说,JSESSIONID是一个普通的Cookie,但是J2EE服务器把它作为特定的Cookie。服务器端维护着一个 JSESSIONID 列表,标识多个Cookie的值,分别对应一个客户端浏览器会话。客户端浏览器每发送一个请求都把这个Cookie发送过来,服务器就可以根据客户端浏览器发送的Http请求头部分中的 JSESSIONID 查找该表“识别”该客户端会话。服务器端针对HttpSession接口编程的代码都依赖于这个机制。如在Web应用编程时都是通过HttpSession接口编程上设置特定标志标识客户端是否登录。

2.1.5. Web应用的Session Cookie和单点登录

在某些实现单点登录环境下,为了客户端浏览器能正确回送适当的Cookie,有时需要配置Web应用的Session Cookie的Name、Path等属性,使得浏览器能区分开参与单点登录的各个应用的Cookie。应用服务器软件产品一般都提供配置手段,如在WebLogic Server是在 weblogic.xml 中配置。

2.2. IE浏览器跨域安全特性Cross-Frame Scripting and Security

2.2.1. 禁止跨域脚本访问

参考 https://www.360docs.net/doc/1a13218214.html,/en-us/library/ms533028.aspx

通过运用 DHTML 的对象模型,Html页面不同窗口和框架里的内容可以通过脚本互相作用。但是,由于同一个浏览器可以同时在不同的浏览窗口或框架中显示来自不同服务器的页面,为了保持数据的完整和信息的安全,就必须建立一种强制性的安全性规则。涉及在Html 页面包含的