【问题标题】:HTTP request from a C# desktop application to a Siteminder-protected server从 C# 桌面应用程序到受 Siteminder 保护的服务器的 HTTP 请求
【发布时间】:2015-11-01 22:43:21
【问题描述】:

我开发了一个 C# 桌面应用程序,它向客户的服务器(通常是 Documentum/SharePoint/Alfresco/NemakiWare/etc 基于 HTTPS 的服务器发出 HTTPS 请求)服务器)。

一些客户要求我们支持他们受 CA SSO 保护的服务器(Siteminder 的新名称)。

问题:我需要做什么才能让我的应用程序向受 CA SSO 保护的服务器发送 HTTPS 请求(并接收响应)?

  • 我已经为我们的 C# 桌面应用程序开发了 NTLM-SSO 支持,它运行良好,但我不确定如何继续进行 CA SSO。
  • 我已经问过same question on the CA forum,但与那里的大多数问题一样,它仍未得到答复。

【问题讨论】:

    标签: c# single-sign-on desktop-application siteminder


    【解决方案1】:

    要使用 CA SSO 进行身份验证,然后连接到所需的 URL,我们需要访问配置为使用 CA SSO 身份验证的 Web 服务器上的受保护资源:

    1. 使用 HTTP 请求请求服务器上的资源。
    2. 请求由 Web 服务器接收并被 CA SSO Web 代理拦截。
    3. Web 代理确定资源是否受到保护,如果是,则收集用户的凭据并将其传递给策略服务器。
    4. 策略服务器根据策略存储中包含的规则和策略对用户进行身份验证,并验证通过身份验证的用户是否有权访问所请求的资源。
    5. 用户通过身份验证和授权后,策略服务器将授予对受保护资源的访问权限。

    这是通过以下步骤完成的:

    打开到受保护资源的 URI 的连接(在本例中为 HTTP 请求)。由于请求尚未通过身份验证,CA SSO 代理将发出重定向到登录页面。在代码中,AllowAutoRedirect 设置为 false。这很重要,因为后续步骤 3 中的登录数据 POST 将需要重定向 URL。如果AllowAutoRedirect 为真,则响应将不包含 Location 标头,随后的 POST 将发送到原始 URL,然后再次重定向到登录页面。但是,客户端和服务器之间发生了 POST,在重定向过程中,步骤 3 的请求的负载中携带的任何 POST 数据都将丢失。

    Dim request As HttpWebRequest
    Dim response As HttpWebResponse
    Dim url As String = PROTECTED_URL
    
    request = WebRequest.Create(url)
    request.AllowAutoRedirect = False
    response = request.GetResponse
    
    ' make sure we have a valid response
    If response.StatusCode <> HttpStatusCode.Found Then
        Throw New InvalidProgramException
    End If
    
    ' get the login page
    url = response.Headers("Location")
    request = WebRequest.Create(url)
    request.AllowAutoRedirect = False
    response = request.GetResponse
    

    下一步涉及创建一个 HTTPS 请求,将所有表单数据(包括用户 ID 和密码)发送回服务器。身份验证代理的目的是通过验证用户 ID 和密码来验证用户的身份。因此,他们的 URL 自然地使用 SSL(安全套接字层)并为我们加密,因此我们不需要在我们的程序中进一步加密。但是,POST 数据的格式很有趣,因为有两种选择。示例程序使用更简单的方法将内容类型设置为 application/x-www-form-urlencoded。此处 POST 数据的格式类似于查询字符串,并作为下一个请求的一部分发送。

    Dim postData As String
    
    postData = ""
    For Each inputName As String In tags.Keys
        If inputName.Substring(0, 2).ToLower = "sm" Then
            postData &= inputName & "=" & _
                        HttpUtility.UrlEncode(tags(inputName)) & "&"
        End If
    Next
    postData += "postpreservationdata=&"
    postData += "USER=" + HttpUtility.UrlEncode(USERNAME) & "&"
    postData += "PASSWORD=" + HttpUtility.UrlEncode(PASSWORD)
    
    request = WebRequest.Create(url)
    cookies = New CookieContainer
    request.CookieContainer = cookies
    request.ContentType = FORM_CONTENT_TYPE
    request.ContentLength = postData.Length
    request.Method = POST_METHOD
    request.AllowAutoRedirect = False   ' Important
    
    Dim sw As StreamWriter = New StreamWriter(request.GetRequestStream())
    sw.Write(postData)
    sw.Flush()
    sw.Close()
    
    response = request.GetResponse
    

    【讨论】:

    • 看起来很棒!你会碰巧在 C# 中有相同的代码吗?用户/密码 POST 完成后,是否可以像 Siteminder 不存在一样正常发送请求,还是需要添加某种标头之类的?
    • 如果我理解正确,第一个请求必须是 HTTP,第二个请求必须是 HTTPS?如果是这样,您能否更正您的句子“下一步涉及创建一个 POST 所有表单数据的 HTTP 请求”它应该是 HTTPS 对吗?谢谢你:-)
    【解决方案2】:

    与 Mohit 的答案相同,但可以使用更简单的代码来完成:

            //Make initial request for SM to give you some cookies and the authentication URI
            RestClient client = new RestClient("http://theResourceDomain/myApp");
            client.CookieContainer = new CookieContainer();
            IRestResponse response = client.Get(new RestRequest("someProduct/orders"));
    
            //Now add credentials.
            client.Authenticator = new HttpBasicAuthenticator("username", "password");
            //Get resource from the SiteMinder URI which will redirect back to the API URI upon authentication.
            response = client.Get(new RestRequest(response.ResponseUri)); 
    
    • 虽然这使用了 RestSharp,但可以使用 HttpClient 甚至 HttpWebRequest 轻松复制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多