65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.79/5 (6投票s)

2004年8月13日

4分钟阅读

viewsIcon

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”是其安全功能。

Sample Image

解决方案方法

  1. 会话维护:

    Weblogic 服务器通过唯一的标识符 jsessionid 来维护其会话。客户端的每个 HTTP 请求都通过此 jsessionid 进行标识,以便跟踪与客户端的会话。这种会话跟踪有两种方式:

    • 作为从浏览器发送的 cookie

    • 作为 URL 重写,将 jsessionid 作为查询字符串附加到每个请求中
  2. 安全维护:

    本例中与 Weblogic 和 Sun One portal 一起实现的安全功能是“Webseal”。Webseal 通过在成功登录后生成一个 webseal 标识符,并将其作为 cookie (PD-H-SESSION-ID) 发送以跟踪后续请求,来授权其允许访问的每个资源。如果在后续请求中未能正确识别该会话 cookie,则“Web Seal”会拒绝访问资源。

    Cookie 值
    Cookie 名称 备注
    PD-H-SESSION-ID 为每个会话随机生成 由 WebSeal 生成
    Cookie 名称 为每个会话随机生成 由 WebLogic 生成

  3. 数据交换:

    由于访问 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 的应用程序:

  1. 通过启动的浏览器窗口像普通 Web 应用程序一样访问,通过将 jessionid 附加到 URL。

    JSESSIONID cookie 值被作为查询字符串参数附加到 URL。

    例如:http://www.yyyy.com/UI123?JSESSIONID=xxxxx。

  2. 通过 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.XMLHTTPxmlHTTP 对象的功能。

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 服务进行交互。

历史

这是初始版本。欢迎所有评论。

© . All rights reserved.