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):
开发者_StackOverflow中文版 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();
}
}
}
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.
Here is an alternative method if you want to use HttpWebResponse
/HttpWebRequest
:
public static HttpWebResponse requestSecureDocument(HttpWebRequest _request, string _rtcServerURL, string _userName, string _password)
{
//FormBasedAuth Step1: Request the resource and clone the request to be used later
HttpWebRequest _requestClone = WebRequestExtensions.CloneRequest(_request, _request.RequestUri);
//(HttpWebRequest)WebRequest.Create(request.RequestUri);
//store the response in _docResponse variable
HttpWebResponse _docResponse = (HttpWebResponse)_request.GetResponse();
//HttpStatusCode.OK indicates that the request succeeded and that the requested information is in the response.
if (_docResponse.StatusCode == HttpStatusCode.OK)
{
//X-com-ibm-team-repository-web-auth-msg header signifies form based authentication is being used
string _rtcAuthHeader = _docResponse.Headers["X-com-ibm-team-repository-web-auth-msg"];
if (_rtcAuthHeader != null && _rtcAuthHeader.Equals("authrequired"))
{
_docResponse.GetResponseStream().Flush();
_docResponse.Close();
//Prepare form for authentication as _rtcAuthHeader = authrequired
HttpWebRequest _formPost = (HttpWebRequest)WebRequest.Create(_rtcServerURL + "/j_security_check");
_formPost.Method = "POST";
_formPost.Timeout = 30000;
_formPost.CookieContainer = _request.CookieContainer;
_formPost.Accept = "text/xml";
_formPost.ContentType = "application/x-www-form-urlencoded";
String _authString = "j_username=" + _userName + "&j_password=" + _password;
//create authentication string
Byte[] _outBuffer = Encoding.UTF8.GetBytes(_authString); //store in byte buffer
_formPost.ContentLength = _outBuffer.Length;
Stream _str = _formPost.GetRequestStream();
_str.Write(_outBuffer, 0, _outBuffer.Length); //update form
_str.Close();
//FormBasedAuth Step2:submit the login form and get the response from the server
HttpWebResponse _formResponse = (HttpWebResponse)_formPost.GetResponse();
_rtcAuthHeader = _formResponse.Headers["X-com-ibm-team-repository-web-auth-msg"];
//check if authentication has failed
if (_rtcAuthHeader != null && _rtcAuthHeader.Equals("authfailed"))
{
//authentication failed. You can write code to handle the authentication failure.
//if (DEBUG) Console.WriteLine("Authentication Failure");
}
else
{
//login successful
_formResponse.GetResponseStream().Flush();
_formResponse.Close();
//FormBasedAuth Step3: Resend the request for the protected resource.
//if (DEBUG) Console.WriteLine(">> Response " + request.RequestUri);
return (HttpWebResponse)_requestClone.GetResponse();
}
}
}
//already authenticated return original response_docResponse
return _docResponse;
}
You can call this function in your code -
string _serverURL = https://localhost:9443/ccm;
string _resourceURL = "https://localhost:9443/ccm/rootservices";
string mediatype = "application/xml";
string username = "username";
string password = "password";
try
{
CookieContainer _cookies = new CookieContainer();//create cookie container
HttpWebRequest documentGet = (HttpWebRequest)WebRequest.Create(_resourceURL);
documentGet.Method = "GET"; //method
documentGet.CookieContainer = _cookies; //set container for HttpWebRequest
documentGet.Accept = mediatype;
documentGet.Headers.Set("OSLC-Core-Version", "3.0"); //for RTC 3.0.1.2
documentGet.Timeout = 300000;
HttpWebResponse response = requestSecureDocument(documentGet, _serverURL, username, password);
if (response.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine(" Error: " + response.StatusDescription);
response.Close();
}
}
catch (Exception ex)
{
}
You can read more at my blog.
精彩评论