Search code examples
c#postcurlhttpwebrequestjazz

c# - WebRequest HTTP POST with Cookie (port from curl script)


The IBM RTC RESTful api gives an example of a shell script for authenticating with the server:

COOKIES=./cookies.txt

USER=my_user
PASSWORD=my_password
HOST="https://myJazzServer:9092/jazz"

curl -k -c $COOKIES "$HOST/authenticated/identity"

curl -k -L -b $COOKIES -c $COOKIES -d j_username=$USER -d j_password=$PASSWORD "$HOST/authenticated/j_security_check"

This works perfectly, however i need to authenticate with the server using c#.

So far i have the following, but it isn't working (returns the authorization failed page):

    CookieContainer _cookie;

    public string _RTC()
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myJazzServer.com:9092/jazz/authenticated/identity");
        if (_cookie == null)
        {
            _cookie = new CookieContainer();
        }
        string a;
        request.CookieContainer = _cookie;
        using (var response = request.GetResponse())
        {
            using (StreamReader sr = new StreamReader(response.GetResponseStream()))
            {
                a = sr.ReadToEnd();
            }
        }




        byte[] data = (new ASCIIEncoding()).GetBytes("j_username=myUser&j_password=MyPass");

        request = (HttpWebRequest)WebRequest.Create("https://myJazzServer.com:9092/jazz/authenticated/j_security_check");

        request.Method = "POST";
        request.ContentType = "text/html";
        request.ContentLength = data.Length;
        request.CookieContainer = _cookie;
        Stream reqStream = request.GetRequestStream();
        reqStream.Write(data,0,data.Length);

        string b;

        using (var response = request.GetResponse())
        {
            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                b = reader.ReadToEnd();
            }
        }
    }

Solution

  • I would suggest you try the following:

    public class WebClientEx : WebClient
    {
        private CookieContainer _cookieContainer = new CookieContainer();
    
        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);
            if (request is HttpWebRequest)
            {
                (request as HttpWebRequest).CookieContainer = _cookieContainer;
            }
            return request;
        }
    }
    
    class Program
    {
        static void Main()
        {
            using (var client = new WebClientEx())
            {
                var response1 = client.DownloadString("https://myJazzServer.com:9092/jazz/authenticated/identity");
    
                var data = new NameValueCollection
                {
                    { "j_username", "myUser" },
                    { "j_password", "MyPass" },
                };
                var response2 = client.UploadValues("https://myJazzServer.com:9092/jazz/authenticated/j_security_check", data);
                Console.WriteLine(Encoding.Default.GetString(response2));
            }
        }
    }
    

    Also to simplify debugging you could activate tracing by putting this in your app.config:

    <configuration>
    
      <system.diagnostics>
        <sources>
          <source name="System.Net.Sockets" tracemode="protocolonly">
            <listeners>
              <add name="System.Net.Sockets" type="System.Diagnostics.TextWriterTraceListener" initializeData="network.log" />
            </listeners>
          </source>
        </sources>
    
        <switches>
          <add name="System.Net.Sockets" value="Verbose"/>
        </switches>
    
        <trace autoflush="true" />
      </system.diagnostics>
    </configuration>
    

    This will create a detailed log file of the network activity which might simplify debugging.