使用 .NET 与基于 j2EE 的 Web 应用程序进行交互






3.79/5 (6投票s)
2004年8月13日
4分钟阅读

73687
一篇关于 .NET 应用程序与基于 j2EE 的 Web 应用程序交互的文章。
引言
企业应用程序集成是当今的主要任务,让不同的技术应用程序之间能够相互通信是一项艰巨的任务。本文介绍了一个基于 .NET 的应用程序如何与运行在 WebLogic 上、位于“Webseal”安全墙后面的基于 j2EE 的应用程序进行通信。为了实现一个基于 j2EE 的应用程序(运行在 Weblogic 上)和 .NET 应用程序的无缝协同工作,需要解决以下主要任务:
- 维护基于 j2EE 的应用程序与 .NET 应用程序之间的会话。
- 维护基于 j2EE 的应用程序中现有的安全框架。
- 在不绑定数据类型的情况下交换数据。
- 在对协议层和端口没有太多限制的情况下交换数据。
背景
Web 服务器应用程序中的框架
VB.NET Windows 客户端应用程序与使用 STRUTS 框架开发的基于 j2EE 的 Web 应用程序交换数据和用户界面,应用程序服务器为 Weblogic 7.0。部署在应用程序服务器上的所有资源(Java 类文件)都必须通过 Sun One Portal 访问,而“Webseal”是其安全功能。
解决方案方法
- 会话维护:
Weblogic 服务器通过唯一的标识符
jsessionid
来维护其会话。客户端的每个 HTTP 请求都通过此jsessionid
进行标识,以便跟踪与客户端的会话。这种会话跟踪有两种方式:- 作为从浏览器发送的 cookie
或
- 作为 URL 重写,将
jsessionid
作为查询字符串附加到每个请求中
- 作为从浏览器发送的 cookie
- 安全维护:
本例中与 Weblogic 和 Sun One portal 一起实现的安全功能是“Webseal”。Webseal 通过在成功登录后生成一个 webseal 标识符,并将其作为 cookie (PD-H-SESSION-ID) 发送以跟踪后续请求,来授权其允许访问的每个资源。如果在后续请求中未能正确识别该会话 cookie,则“Web Seal”会拒绝访问资源。
Cookie 值 Cookie 名称 值 备注 PD-H-SESSION-ID 为每个会话随机生成 由 WebSeal 生成 Cookie 名称 为每个会话随机生成 由 WebLogic 生成 - 数据交换:
由于访问 Web 资源的 .NET 应用程序可能位于防火墙后面,因此决定将所有请求都作为 HTTP 请求。Web 服务器的输出响应将是用户界面的 HTML 页面,或者通过 HTTP 传输的 XML 文档,该文档将在 VB.NET 应用程序端进行解析以处理数据。
解决方案
.NET 应用程序是使用 VB.NET 开发的 Windows 应用程序。IE 控件和 System.web.HTTPUtility
命名空间用于访问基于 j2EE 的 Web 应用程序。
IE 控件用于向基于 j2EE 的 Web 应用程序发出 HTTP 请求,并在需要时将其显示在浏览器窗口中。
System.web.HTTPUtility
用于发出 HTTP 请求,并以 XML 格式获取所需的响应流数据,该响应流来自基于 j2EE 的 Web 应用程序。
使用代码
启动一个新的 IE 进程以控制目标为应用程序登录屏幕的浏览器窗口。
'//Code snippet
'//
'DLL References
' 1) Microsoft.mshtml
' 2) SHDocVw.dll
'Declarations
'Declare libraries...
Friend libSWs As SHDocVw.ShellWindows
Friend libDoc As mshtml.HTMLDocument
Friend WithEvents libIE As SHDocVw.InternetExplorer
Friend objIE As New Object
Private Function InitiateIE ()
Try
Dim strIEExecutablePath As String = ""
StrIEExecutablePath = GetBrowserName ()
If Trim (strIEExecutablePath) <> "" Then
'Initializing shellwindows ...
libSWs = New SHDocVw.ShellWindows
创建一个新进程来控制关闭浏览器窗口时删除所有资源。这很有必要,因为 IE 控件否则会占用资源,因为它会关联到任何已打开的浏览器窗口的现有 IExplore.exe 进程。
'Start the process Info
prcStartInfo = New ProcessStartInfo (strIEExecutablePath,<LOGIN URL>)
prcStartInfo.WindowStyle = ProcessWindowStyle.Minimized
prcStartInfo.UseShellExecute = True
'Create a new process...
SetStatusText(DOWNLOADING_IN_PROGRESS)
prcInitprocess = New Process
prcInitprocess.StartInfo = prcStartInfo
prcInitprocess.Start()
prcInitprocess.WaitForInputIdle ()
'Get the handle of the window
pWHnd = prcInitprocess.MainWindowHandle
hWndIe = pWHnd.ToInt64
For Each objIE In libSWs
If TypeName(objIE) = "IWebBrowser2" Then
'Condition checking for getting a specific IE
'Checking based on window handle information
libIE = objIE
If hWndIe = libIE.HWND Then
'Hide the addressbar, MenuBar and toolbar.
'The Browser application is without address bar,
'menu bar and toolbar...
libIE.AddressBar = False
libIE.MenuBar = False
libIE.ToolBar = False
libIE.Visible = True
'Set the Browser Window in the front in normal state...
SetWindowFront (hWndIe)
While libIE.ReadyState <> READYSTATE_COMPLETE
'Lock the thread
End While
If libIE.ReadyState = READYSTATE_COMPLETE Then
'setting the document object
libDoc = libIE.Document
SetStatusText(DOWNLOADING_COMPLETED)
blnSessionflg = False
blnIsLoginEnabled = True
blnTimerEnabled = True
End If
End If
End If
Next
End If
Catch exp As Exception
MessageBox.Show(exp.ToString)
End Try
End Function
'//
填充登录凭据并提交进行身份验证。Webseal 对有效用户进行身份验证,并发送一个安全 cookie () 以及应用程序的主页/初始页。在应用程序主页/初始页的浏览器下载事件中,通过 System.Web.httputility
从文档 cookie 读取安全 cookie 并进行存储,以供后续请求使用。在下面的代码片段中,还跟踪了 Weblogic 会话 (jsessionid
),因为登录后会访问 Weblogic 的主页,从而创建一个新会话。
'//Code snippet '// 'This function is called in the download event of the 'browser window. It retrieves the webseal and weblogic 'cookie values for appending it in subsequent requests 'for maintaining the session values... Public Function TrackSession() Try For Each objIE in libSWs If TypeName(objIE) = "IWebBrowser2" Then 'if this is an HTML page, navigate. libIE = objIE 'Checking whether same window handle If hWndIe = libIE.HWND Then libIE.AddressBar = False libIE.MenuBar = False libIE.ToolBar = False libIE.Visible = True 'See if the weblogic session has been created and track the 'cookie information required for authentication... 'setting the document object libDoc = libIE.Document Dim title As String 'Capture the browser instance that has this title 'and use the same for future calls. title = "MY title" If libDoc.title = title Then 'Get the cookie val. strCookieVal = libDoc.cookie 'SetNetCookieCollection(strCookieVal) str_g_cookieval = strCookieVal 'Parse and assign the cookie val.... ParseCookie(strCookieVal) 'set the session value as on blnSessionflg = True Exit For End If End If End If Next Catch exp as Exception End Try End Function Private Function ParseCookie (ByVal strCookie As String) As String 'Assigns webseal and jession identifier values... Dim arrCookieVal() As String Dim strWebLogicCookie As String Dim arrWebLogicCookie() As String Dim strWebSealCookie As String Dim arrWebSealCookie() As String Dim intCounter As Integer arrCookieVal = strCookie.Split(";") For intCounter = 0 To arrCookieVal.Length - 1 If InStr(arrCookieVal(intCounter), "SESSION_IDS_OF_ADAPTER") Then strWebLogicCookie = arrCookieVal(intCounter) arrWebLogicCookie = strWebLogicCookie.Split("#") JSESSION_ID = JSESSION_ID & arrWebLogicCookie(1) strMethodUrl = strMethodUrl & JSESSION_ID ElseIf InStr(arrCookieVal(intCounter), "PD-H-SESSION-ID") Then strWebSealCookie = arrCookieVal(intCounter) arrWebSealCookie = strWebSealCookie.Split("=") WEB_SEALCOOKIE_NM = arrWebSealCookie(0) WEB_SEALCOOKIE_VAL = arrWebSealCookie(1) End If Next End Function
一旦在 VB.NET 应用程序中获得了安全和会话 cookie,就可以如下访问基于 j2EE 的应用程序:
- 通过启动的浏览器窗口像普通 Web 应用程序一样访问,通过将
jessionid
附加到 URL。JSESSIONID
cookie 值被作为查询字符串参数附加到 URL。例如:http://www.yyyy.com/UI123?JSESSIONID=xxxxx。
- 通过
System.web.httputility
通过 HTTP 响应获取 XML 数据。Webseal 会话 cookie 值 (PD-H-SESSION-ID) 首先在请求的 URL 上设置,然后发出方法调用请求,并将
JSESSIONID
cookie 值作为查询字符串参数附加到 URL。例如:http://www.yyyy.com/MC123?JSESSIONID=xxxxx。
'//Code snippet
'//
'Accessing web application through initiated browser window:
NavigateToUrl(http://www.yyyy.com/UI123?JSESSIONID=xxxxx.)
'Navigates to the specified url in IE browser window...
Public Function NavigateToUrl(ByVal strUrl As String, _
ByVal blnAsync As Object, ByVal trgFrame As Object, _
ByVal objPostData As Object, ByVal objHeader As Object)
'Navigates to the specified url in IE browser window...
Try
For Each objIE In libSWs
'Checking based on window handle information
If TypeName(objIE) = "InternetExplorerClass" _
Or TypeName(objIE) = "IWebBrowser2" Then
libIE = objIE
'Checking whether same window handle
If hWndIe = libIE.HWND Then
libIE.AddressBar = False
libIE.MenuBar = False
libIE.ToolBar = False
libIE.Visible = True
'Navigate to the specified URL
libIE.Navigate(strUrl, blnAsync, _
trgFrame, objPostData, objHeader)
'Track the download status and
'if download is complete
'display the page
While libIE.ReadyState <> READYSTATE_COMPLETE
Application.DoEvents()
End While
Exit For
End If
End If
Next
Catch exp As Exception
Messagebox(exp.ToString)
End Try
End Function
通过 System.web.httputility 访问 Web 应用程序
用于发出方法调用的源代码片段(HTTP 上的 XML)。
此类代表了 MSXML.XMLHTTP
中 xmlHTTP
对象的功能。
Imports System.Net
Imports System.Web.HttpUtility
''Sample Execution flow
Function main ()
'Setting Method Call URL
StrMethdoURL ="http://www.yyy.com/ IntegrationServlet;" & _
" jsessionid=AhFj18NaW5AEe1o0EvNH1u1gw8P3Yjq" & _
"1TMNUyWiSI1t2ce0TJL9Y!567889692! 1075906019681"
'Setting Post Data
PostData = "TargetName=GetPreOrders&FromDate=&ToDate=&ReferenceNo=1"
'XML Response in string
response = ProcessData(strMethdoURL,PostData)
End Function
Public Function ProcessData(ByVal strUrl As String, _
ByVal postdata As String) As String
'Opens an url connection, posts the parameters,
'gets the response as XML string
'Validated XML is displayed.
Dim xmlHTTP As New XMLHTTP
Dim strXML As String
xmlHTTP.open("POST", strUrl)
xmlHTTP.Send(postdata)
strXML = xmlHTTP.ResponseText()
DisplayXML(ParseXML(strXML))
ProcessData = strXML
End Function
Public Class XMLHTTP
'Makes an internet connection to specified URL
Public Overridable Sub open(ByVal bstrMethod As String, _
ByVal bstrUrl As String, Optional ByVal varAsync As _
Object = False, Optional ByVal bstrUser _
As Object = "", Optional ByVal bstrPassword As Object = "")
Try
strUrl = bstrUrl
strMethod = bstrMethod
'Checking if proxy configuration
'is required...(blnIsProxy value
'from config file)
If blnIsProxy Then
'Set the proxy object
proxyObject = WebProxy.GetDefaultProxy()
'Finding if proxy exists and if so set
'the proxy configuration parameters...
If Not (IsNothing(proxyObject.Address)) Then
uriAddress = proxyObject.Address
If Not (IsNothing(uriAddress)) Then
_ProxyName = uriAddress.Host
_ProxyPort = uriAddress.Port
End If
UpdateProxy()
End If
urlWebRequest.Proxy = proxyObject
End If
'Make the webRequest...
urlWebRequest = System.Net.HttpWebRequest.Create(strUrl)
urlWebRequest.Method = strMethod
If (strMethod = "POST") Then
setRequestHeader("Content-Type", _
"application/x-www-form-urlencoded")
End If
'Add the cookie values of jessionid of weblogic
'and PH-Session value of webseal
'for retaining the same session
urlWebRequest.Headers.Add("Cookie", str_g_cookieval)
Catch exp As Exception
SetErrStatusText("Error opening method level url connection")
End Try
End Sub
'Sends the request with post parameters...
Public Overridable Sub Send(Optional ByVal objBody As Object = "")
Try
Dim rspResult As System.Net.HttpWebResponse
Dim strmRequestStream As System.IO.Stream
Dim strmReceiveStream As System.IO.Stream
Dim encode As System.Text.Encoding
Dim sr As System.IO.StreamReader
Dim bytBytes() As Byte
Dim UrlEncoded As New System.Text.StringBuilder
Dim reserved() As Char = {ChrW(63), ChrW(61), ChrW(38)}
urlWebRequest.Expect = Nothing
If (strMethod = "POST") Then
If objBody <> Nothing Then
Dim intICounter As Integer = 0
Dim intJCounter As Integer = 0
While intICounter < objBody.Length
intJCounter = _
objBody.IndexOfAny(reserved, intICounter)
If intJCounter = -1 Then
UrlEncoded.Append(System.Web.HttpUtility.UrlEncode(objBody.Substring(intICounter, _
objBody.Length - intICounter)))
Exit While
End If
UrlEncoded.Append(System.Web.HttpUtility.UrlEncode(objBody.Substring(intICounter, _
intJCounter - intICounter)))
UrlEncoded.Append(objBody.Substring(intJCounter, 1))
intICounter = intJCounter + 1
End While
bytBytes = _
System.Text.Encoding.UTF8.GetBytes(UrlEncoded.ToString())
urlWebRequest.ContentLength = bytBytes.Length
strmRequestStream = urlWebRequest.GetRequestStream
strmRequestStream.Write(bytBytes, 0, bytBytes.Length)
strmRequestStream.Close()
Else
urlWebRequest.ContentLength = 0
End If
End If
rspResult = urlWebRequest.GetResponse()
strmReceiveStream = rspResult.GetResponseStream()
encode = System.Text.Encoding.GetEncoding("utf-8")
sr = New System.IO.StreamReader(strmReceiveStream, encode)
Dim read(256) As Char
Dim count As Integer = sr.Read(read, 0, 256)
Do While count > 0
Dim str As String = New String(read, 0, count)
strResponseText = strResponseText & str
count = sr.Read(read, 0, 256)
Loop
Catch exp As Exception
SetErrStatusText("Error while sending parameters")
WritetoLog(exp.ToString)
End Try
End Sub
'Setting header values...
Public Overridable Sub setRequestHeader(ByVal bstrHeader _
As String, ByVal bstrValue As String)
Select Case bstrHeader
Case "Referer"
urlWebRequest.Referer = bstrValue
Case "User-Agent"
urlWebRequest.UserAgent = bstrValue
Case "Content-Type"
urlWebRequest.ContentType = bstrValue
Case Else
urlWebRequest.Headers(bstrHeader) = bstrValue
End Select
End Sub
Private Function UpdateProxy()
Try
If Not (IsNothing(uriAddress)) Then
If ((Not IsNothing(_ProxyName)) And _
(_ProxyName.Length > 0) And (_ProxyPort > 0)) Then
proxyObject = New WebProxy(_ProxyName, _ProxyPort)
Dim strByPass() As String = Split(strByPassList, "|")
If strByPass.Length > 0 Then
proxyObject.BypassList = strByPass
End If
proxyObject.BypassProxyOnLocal = True
If blnNetworkCredentials Then
If strDomain <> "" Then
proxyObject.Credentials = New _
NetworkCredential(strUserName, _
strPwd, strDomain)
Else
proxyObject.Credentials = New _
NetworkCredential(strUserName, _
strPwd)
End If
End If
End If
End If
Catch exp As Exception
SetErrStatusText("Error while updating proxy configurations")
WritetoLog(exp.ToString)
End Try
End Function
'Property for setting the Responsetext
Public Overridable ReadOnly Property ResponseText() As String
Get
ResponseText = strResponseText
End Get
End Property
Private urlWebRequest As System.Net.HttpWebRequest
Private urlWebResponse As System.Net.HttpWebResponse
Private strResponseText As String
Private strUrl As String
Private strMethod As String
Private proxyObject As WebProxy
Private intCount As Integer
Private uriAddress As Uri
Private _ProxyName As String
Private _ProxyPort As Integer
End Class
'//
关注点
通过定义一个 XML 模式来维护两个应用程序之间的数据完整性,该模式通过 HTTP 上的 XML 进行交换,也可以是 Web 服务。如果通过安全协议层访问 j2EE,则可以使用 System.Security.Cryptography.X509Certificates
命名空间,并对 HTTPS 请求进行授权。
'//Authorizes SSL Trust Certification
System.Net.ServicePointManager.CertificatePolicy = New CertificatePolicy
上述方法也可以用于 ASP.NET 应用程序与基于 j2EE 的应用程序或任何可以通过端口 8080 或 443 访问的 Web 服务进行交互。
历史
这是初始版本。欢迎所有评论。