ibm tivoli_Tivoli Access Manager WebSEAL环境中的AJAX技术

ibm tivoli

Web开发中使用的编程技术和范例正在Swift变化。 当今使用的主流技术之一是异步JavaScript和XML(AJAX)。 本文介绍了在集中式反向代理环境(例如Tivoli Access Manager WebSEAL)中部署AJAX应用程序的最佳实践。

但是,在继续之前,本文将简要介绍和回顾相关的WebSEAL概念。

背景:WebSEAL在传统的请求/响应范例中运行

WebSEAL是使用URL重写以提供其某些核心功能的反向代理。 反向代理的作用是提供一个集中点,以代表后端Web服务器接收HTTP请求。 当反向代理接收到HTTP请求时,它使用联结(类似于UNIX®安装)来确定将请求传递到哪个后端Web服务器(请参见图1-1)。 通常,为了使Web服务器有意义,需要重写URL。 然后,重写的请求将发送到后端服务器。 后端Web服务器将请求作为标准HTTP GET请求接受并进行相应处理。

图1-1。 反向代理请求处理
反向代理请求处理

反向代理充当中介的第二点是通过过滤来自后端Web服务器的响应以替换所有URL以包括联结详细信息(请参见图1-2)。 这样可以确保返回HTML页面中的所有链接都指向有效的URL。

图1-2。 反向代理响应处理
反向代理响应处理

在充分考虑WebSEAL将如何与AJAX应用程序一起使用之前,必须了解WebSEAL用于过滤HTML内容中的URL的基本规则。 这些规则根据环境中部署的联结类型而有所不同。 以下各节介绍每种URL。

相对网址的过滤规则

相对URL始终由浏览器正确处理。 因此,WebSEAL不会过滤相对URL。

表1.示例-相对URL
浏览器<-> IBM Tivoli WebSEAL WebSEAL <->后端Web服务器
请求 GET“ example.html” GET“ example.html”
响应
<html>
    <head>
        <title>Example Page</title>
    </head>
    <body>
        <a href="../sample.html">Sample link</a>
    </body>
</html>
<html>
    <head>
        <title>Example Page</title>
    </head>
    <body>
        <a href="../sample.html">Sample link</a>
    </body>
</html>

服务器相对URL的过滤规则

WebSEAL必须将联结名称添加到服务器相对URL的路径中,该URL引用位于联结服务器上的资源。

表2.示例:服务器相对URL
浏览器<-> IBM Tivoli WebSEAL WebSEAL <->后端Web服务器
请求 GET“ /junction/html/example.html” GET“ /html/example.html”
响应
<html>
    <head>
        <title>Example Page</title>
    </head>
    <body>
        <a href="/junction/html/sample.html">Sample link</a>
    </body>
</html>
<html>
    <head>
        <title>Example Page</title>
    </head>
    <body>
        <a href="/html/sample.html">Sample link</a>
    </body>
</html>

绝对URL的过滤规则

WebSEAL必须将联结名称添加到引用位于联结服务器上的资源的绝对URL的路径中。 缺省情况下,WebSEAL将绝对URL更改为相对于服务器的URL。 rewrite-absolute-with-absolute参数确定是否使用绝对URL。 此参数位于WebSEAL配置文件中,该文件默认情况下位于WEBSEAL_HOME / etc / webseald- instance .conf中。

表3.示例:绝对URL
浏览器<-> IBM Tivoli WebSEAL WebSEAL <->后端Web服务器
请求 GET“ http://www.ibm.com/junction/html/example.html” GET“ http://www.backend.com/html/example.html”
响应
<html>
    <head>
        <title>Example page</title>
    </head>
    <body>
        <a href="/junction/html/sample.html">Sample link</a>
    </body>
</html>
<html>
    <head>
        <title>Example Page</title>
    </head>
    <body>
        <a href="http://www.backend.com/html/sample.html">
        Sample link</a>
    </body>
</html>
响应(rewrite-absolute- with-absolute = yes)
<html>
    <head>
        <title>Example page</title>
    </head>
    <body>
        <a href="http://www.ibm.com/junction/html/sample.html">
        Sample link</a>
    </body>
</html>
<html>
    <head>
        <title>Example page</title>
    </head>
    <body>
        <a href="http://www.backend.com/html/sample.html">
        Sample link</a>
    </body>
</html>

将AJAX添加到方程式

以下各节考虑将AJAX添加到WebSEAL环境中的含义。

AJAX编程技术简介

出于本文的目的,假定AJAX请求是使用通过客户端JavaScript对远程系统发出异步请求的任何技术。 理想情况下,响应对象应该是有效的XML文档或XHTML,但是实际上并非总是如此。 这样,本文解决了使用纯文本响应数据时可能出现的其他潜在问题。

有两种用于执行AJAX请求的主流技术: XMLHttpRequest对象和IFRAMEs 。 如下所述。

XMLHttpRequest对象的剖析

XMLHttpRequest对象提供了通过JavaScript异步发出GET和POST请求所需的方法和属性。 清单1-3分别概述了实例化对象,发出请求和处理响应的基本操作。

清单1.实例化一个请求对象
// Internet Explorer
var xhr = new ActiveXObject(Microsoft.XMLHTTP);

//Mozilla, Opera
var xhr = new XMLHttpRequest()
清单2.发出请求
xhr.onreadystatechange = yourCallbackFunction();
xhr.open(method, url, async)
xhr.send(data)
	
//where: 
//	method 	= GET or POST
//	url		= Url to request / post to. 
//	async	= Send request asynchronously (t/f) 
//	data		= Post data (use null for get)
清单3.处理响应
// Useful properties and methods
xhr.responseText 			// The response as a string
xhr.responseXML  			// The response as XML
xhr.getResponseHeaders()	// Get http headers

具有IFRAME的AJAX

AJAX方法也可以通过使用IFRAMEs来完成。 本质上,您可以将内容加载到隐藏的IFRAME中,并在加载时向用户显示。 这是非阻塞的,并提供了一种替代方式来异步加载内容,而无需使用XMLHttpRequest对象。

清单4-6演示了创建IFRAME,添加事件侦听器以及显示和隐藏IFRAME的过程。

清单4.创建一个IFRAME
// Create the IFRAME 
myIFrame = document.createElement(â????IFRAMEâ????);

// Set some basic properties
myIFrame.id                     = â????my_idâ????;
myIFrame.name                   = â????my_iframeâ????;
myIFrame.height                 = â????500â????;
myIFrame.width                  = â????500â????;
myIFrame.style.visibility       = â????visibleâ????;

// Add the IFRAME to the page
document.body.appendChild(â????loadâ????, contentLoaded, true);
清单5.添加事件侦听器
myIFrame.addEventListener(â????loadâ????, doThisWhenLoaded, true);
// where doThisWhenLoaded is the function that is called when 
// the IFRAME is loaded.
清单6.显示和隐藏框架
myIFrame.style.visibility   = â????visibleâ????;
myIFrame.style.visibility   = â????hiddenâ????;

AJAX开发人员注意事项

以下各节解决了在WebSEAL环境中进行编程时AJAX开发人员应考虑的问题。 提供每个问题的示例以及可能的解决方案。 不能总是给出确切的解决方案,因为可能需要考虑环境细节。

这些部分包括:

用户会话到期

问题

在正常操作条件下,如果会话因超时而过期,则当用户下次请求受保护页面时,会将用户重定向到登录页面。 成功登录后,它们将重定向到请求的Web上下文。 如果AJAX是用于发出请求的机制,则登录表单将包含在AJAX响应对象中,并且很有可能重定向将失败。

同样,如果启用了最大数量的并发会话策略,则当AJAX是请求背后的驱动机制时会出现问题。 并发会话策略限制了用户一次可以打开的最大会话数。 根据配置设置,WebSEAL将询问用户是要替换活动的会话还是只是终止其他会话而无需用户干预。 如果启用了提示会话位移,则执行位移的用户不会重定向到位移页面。 在这两种情况下,如果流离失所的用户的下一个请求是通过AJAX完成的,则很有可能无法正确通知用户有关流离失所的信息。

图2.会话到期
示例使用AJAX时会话到期如何导致问题

在正常操作条件下,用户的浏览器将以可接受的方式处理这种类型的响应。 即,重定向到适当的登录表单或错误消息。 但是,当WebSEAL返回的重定向隐藏在XMLHttpRequest对象中时,不会发生此重定向,因此,不会以可接受的方式通知用户为何未批准其最后一个请求。

潜在的解决方案此问题要求客户端能够识别响应对象何时不是预期的格式。 例如,如果响应对象包含HTTP状态代码,而不是“ 200 OK”。 响应对象可能不是应用程序期望的对象。 如果客户端可以检测到此问题,则可以通过将控制权传递给用户代理来有效地升级问题。 通过使用户代理发出相同的请求,而不是在AJAX的子上下文中发出相同的请求,将按照后端应用程序的预期显示错误消息/表单。

清单7.处理会话到期
XMLHttpRequest xhr = new XMLHttpRequest();

// Need to alter how we handle the response slightly
xhr.onreadystatechange = function(requestedUrl){

    if(xhr.readystate = READYSTATE_LOADED){
        try{
            // Assume that anything other than a HTTP status code of 
            // 200 OK is going to be something needing to be handled
            // by the browser. 
            if(xhr.status != HTTP_STATUS_OK){
                throw requestedUrl;
            }else{
                // Handle things normally here 
            }
        }catch(url){
            // Redirect them to the correct page by re-requesting
            // the original URL using the browser as the 
            // user agent rather than an AJAX request. 
            window.location = url;
        }
    }       
}

清单7提供了解决此问题的简化解决方案。 它涉及确保请求返回“ 200 OK”状态,如果没有,则告知浏览器重定向到原始URL。 在这种情况下,如果用户的会话已过期,则用户将被重定向到登录页面。

持久连接

问题

维护客户端和Web服务器之间的持久连接已成为AJAX环境中的一种流行技术,尽管它并不特定于此类环境。 持久连接和HTTP的非传统用法的常见原因是模拟从服务器到客户端的异步通信。 应用程序可能希望对通知或服务器状态等功能执行此操作。 Lotus®Sametime®和感知功能就是一个示例,该功能使服务器可以监视用户的联机状态并显示传入的聊天消息等。 这些连接之一超时时,客户端将尝试立即重新连接到服务器。

对于WebSEAL而言,这意味着除了具有从其他用户发起的请求生成的较短的连接之外,具有活动会话的用户还将保持与服务器的至少一个长期运行的连接。 这将消耗WebSEAL工作线程,并且[server] worker-threads参数的值可能需要在WebSEAL配置文件中进行调整。 在预计会有大量活动用户会话的极端情况下,可能有必要添加WebSEAL实例。

图3.持久连接
持久连接

潜在解决方案

确定在WebSEAL配置文件中配置的[server] worker-threads参数的当前设置是否存在问题。 确定是否存在问题的最简单方法是使用WebSEAL统计信息功能。 具体来说,监视pdweb.threads组件的输出。

以下示例显示了pdweb.threads组件的statistics get命令的输出:

#pdadmin> server task default-webseald-instance stats get pdweb.threads 
active : 0 total : 50

如果报告的“活动”值不断达到“总计”的值,则应使更多工作线程可用。

有关配置WebSEAL工作线程的更多详细信息,请参考《 WebSEAL性能调整指南》 。 有关收集WebSEAL统计信息的更多详细信息,请参阅《 Tivoli Access Manager电子商务问题确定指南》和《 Tivoli Access Manager电子商务审计指南》 。

认证与授权

问题

从未经身份验证的帐户或特权低于所需权限的帐户访问受保护的对象将分别返回登录提示或“ HTTP 401”错误。 用户代理(例如浏览器)了解如何处理这些情况。 但是,使用AJAX作为请求机制的典型客户端将无法理解。

图4.受保护的网站
示例网站结构。

对于公共可访问的典型Web应用程序,它包含指向受保护空间中Web对象的链接是完全可行的。 在这种情况下,当未经身份验证的用户单击链接时,他们将被重定向到适当的身份验证机制。 在对它们进行身份验证后,可以决定是否授权他们访问此特定的Web资源。 如果未获得授权,则会向浏览器发送“ 401未经授权”的消息。 HTTP状态代码。

同样,如果需要做出身份验证或授权决定时,如果AJAX是发出请求的基础介质,则会出现问题。 这些问题遵循与用户会话到期部分中所述相同的模式。 在这种情况下,由于客户端脚本有效地充当了用户代理(浏览器),因此它需要能够以类似的方式处理响应。 也就是说,通知用户他们需要进行身份验证才能访问所请求的资源,并且访问权限不足。

潜在解决方案

这里的解决方案再次归结为在客户端应用程序中内置一些智能。 应用程序在非标准操作条件下执行的能力是Web应用程序开发人员要考虑的重要一点。 如“用户会话”中所述的类似解决方案 问题可以在这里实现。 另一种方法可能是在可能做出身份验证或授权决定的情况下,简单地避免使用AJAX作为请求介质。 无论在此做出什么决定,对于Web开发人员来说,在设计其应用程序时都要牢记这一问题,这一点很重要。

链接重写和相同来源策略

问题

对于标准的WebSEAL联结,仅在配置为执行JavaScript过滤的情况下才执行。 也就是说,使用-j选项创建联结。

大多数Web开发人员将编写其JavaScript代码以包含URL信息。 WebSEAL不会重写此URL信息,因此可能引起各种问题,主要是死链接。 但是,由于JavaScript语言强制执行相同的原始策略 ,因此使用XMLHttpRequest对象发出的请求也存在特定问题。

下面的示例演示Web开发人员通常如何编写其AJAX内容。 通过将JavaScript操作与HTML内容分开,可以更好地重用资源。 但是,如果在JavaScript中定义了URL内容,那么您将需要在WebSEAL中启用脚本过滤。 请考虑以下情形。

清单8. example.js的内容
const server = â????sales.acme.orgâ????;
const port   = â????80â????;

// A custom wrapper the XMLHttpRequest object that I wrote
var xhr = new XHR();        
function doAjaxRequest(){
    var url_1 = â????http://sales.acme.org/sales.xmlâ????;
    var url_2 = â????http://â???? + server + â????:â???? + port + â????/sales.xmlâ????;
    var url_3 = â????/sales.xmlâ????;
    var url_4 = â????sales.xmlâ????;
    xhr.setStateChangeCallback(4, doCallback, this);
        xhr.request(â????GETâ????, url_1, false, null);
}

function doCallback(){
    alert(â????A response was received.â????);
}
清单9. example.html的内容
<html>
    <head>
        <script type=â????text/javascriptâ???? src=â????example.jsâ????></script>
    </head>
    <body>
        <a href=â????javascript:doAjaxRequest()â????>Do Ajax Request</a>
    </body>
</html>

在上面的示例中,出现以下问题。

  • 除非已正确配置脚本过滤,否则不会重写URL。
  • 如果未重写“ http://sales.acme.org/sales.xml”链接,则浏览器将引发异常,这将被视为违反了相同的来源政策。
  • 如果启用了脚本过滤,则WebSEAL将重写example.js中定义的变量“ url_1”。
  • 即使正确配置了脚本过滤,WebSEAL也无法解释“ url_2”中使用的动态链接构建的级别。
  • 尽管WebSEAL具有过滤JavaScript的能力,但是它通常是在旨在作为字符串文字的变量和相对/服务器相对URL之间进行区分。 绝对URL将被正确地重写,并且由于不需要更改相对URL,因此唯一会导致问题的URL类型是相对于服务器的URL。 这是因为WebSEAL必须将联结名称添加到引用位于联结服务器上的资源的服务器相对URL的路径中。 如果无法确定是否声明了类似“?url_3”的变量? 是服务器相对URL,则以这种方式发出的所有请求都将导致无效链接。

潜在解决方案

WebSEAL足够智能,可以过滤JavaScript,但是您需要告诉它这样做。 如果仅打开JavaScript过滤,则不会获得理想的效果。 启用了JavaScript过滤的WebSEAL的标准配置将仅在内容中查找与下表中的条目相似的URL。

表4. JavaScript过滤
未过滤的内容 过滤内容
<a href="javascript:doRequest('http://sales.acme.org/somecontent.html')">点击此处</a> <a href="javascript:doRequest('http://acme.org/sales_junciton/somecontent.html')">点击此处</a>
<script type =“ text / javascript” src =“ // sales.acme.org/js/script.js”> </ script> <script type =“ text / javascript” src =“ // acme.org/sales_junction/js/script.js”> </ script>

要获取在外部JavaScript中定义的内容,您需要使用以下配置:

清单10. webseald.conf中所需的更改
[filter-content-types]
type = text/html
type = text/xml
type = text/javascript

[script-filtering]
script-filter = yes

如果适合您现有的基础架构,则另一种可能的方法是利用虚拟主机联结。 这样,您就有效地消除了在HTML内容中过滤URL的需要。 是时候在客户端脚本中重写URL了,问题就少得多了。 但是,虚拟主机联结不适用于企业内所有WebSEAL部署,因此,实际上要选择最适合您的环境的问题。

连接饼干

问题

使用-j选项创建WebSEAL联结以启用联结cookie时,特殊HTML代码会插入到HTTP响应的开头或结尾,以在浏览器中设置正确的cookie路径(由-j选项确定的位置)。 通常,返回的页面与清单11相似。

清单11.插入联结cookie的示例
<SCRIPT>
    document.cookie = "IV_JCT=%2Fjunction_name";
</SCRIPT>

<html>
    <title>Example page </title>
    <body>
        Rest of the document...
        .
        .
        .

开发人员在使用AJAX发出HTTP请求时需要牢记这一点。 尤其是如果将呈现的响应用作HTML以外的任何其他内容。

例如,一个应用程序可能会发出一个AJAX请求来调用服务器端函数,并期望该结果稍后在调用的应用程序中使用。 如果使用内容类型“ text / html”返回结果,并且使用-j选项配置了联结,那么WebSEAL将插入将联结cookie添加到响应中JavaScript。

图5.连接cookie
连接cookie JavaScript已添加到响应

潜在解决方案

如果来自AJAX请求的响应不呈现为HTML,则不应以“文本/ html”的内容类型发送响应。 应该使用更合适的内容类型,例如“文本/纯文本”。 WebSEAL不会将联结cookie代码添加到内容类型为“ text / html”的响应中。

最佳实践

将意外的HTTP状态代码传播到用户的浏览器

在许多可能的情况下,服务器可能返回的响应不是Web应用程序开发人员所期望的。 其中包括本文前面提到的内容,例如会话到期。 由于用户的浏览器已经具备处理这些情况的能力,因此有必要将控件传回给用户以获得最佳的用户体验。

避免在客户端脚本中动态链接构建。

将URL划分为一系列组件可能具有编程意义。 但是,如果在客户端执行此操作,那么WebSEAL将不会正确过滤URL。

使用相对或绝对链接

尽可能使用相对或绝对链接,以避免死链接问题。 使用JavaScript时,WebSEAL不会触摸服务器相对链接。 这将导致链接失效。

结论

在WebSEAL环境中使用AJAX是可能的,并且在考虑到潜在问题时效果很好。 在这样的环境中进行开发时,如果不考虑URL重写反向代理服务器(如WebSEAL)的技术要求,可能会出现许多潜在的问题。 本文重点介绍了一些潜在的问题,只需遵循概述的最佳做法就可以解决这些问题。


翻译自: https://www.ibm.com/developerworks/tivoli/library/t-ajaxtam/index.html

ibm tivoli

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值