I'm trying to create a little script, that lets you login automatically to a php website.
When I looked at the POST script that is being sent through https, I realized that there is a hidden inputform with a hash string (in the login form hidden with css visibility) which is being send in the data form with the email + password
Example:
login=USERNAME&passwort=PASSWORD&loginhash=1b9f29d68152619b469c3744de3a1f54
So actually I would need to do a simple GET action before the post to parse the string out and then do the POST with the loginhash but how do I keep that connection alive without getting a new hash that is not matching anymore?
//GET
WebRequest req = WebRequest.Create(url);
WebResponse resp = req.GetResponse();
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
reqHtml = sr.ReadToEnd();
}
cookieHeader = resp.Headers["Set-cookie"];
//Parsing html and storing to var loginhash
//POST
string formData = string.Format("login={0}&loginhash={1}&passwort={2}", "USERNAME", loginhash, "PASSWORD");
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.Headers.Add("Cookie", cookieHeader);
byte[] bytes = Encoding.ASCII.GetBytes(formData);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
Update:
Realized, that my theory is actually wrong as I sent two GET's with curl so that curl would pipeline/reuse the connection before. At the end there were still two different hashes in the responses. Maybe the Hash is just a distraction ?
Related
When I post to server using HttpWebRequest and method POST, the NameValueCollection in the asp code has no values. I have identical code working with other server pages, the only difference is the string data posted is a bit different.
code that posts is from a c# desktop application:
string responseFromServer = string.Empty;
System.Net.HttpWebRequest request = null;
System.IO.StreamReader reader = null;
System.Net.HttpWebResponse response = null;
string http = string.Empty;
http = "http://www.apageonmywebsite.aspx";
request = HttpWebRequest.Create(http) as HttpWebRequest;
request.Method = "POST";
UTF8Encoding encoding = new UTF8Encoding();
//send a namevalue pair -that is what the website expects via the request object
string postData = "TRIALID=" + System.Web.HttpUtility.UrlEncode(trialUserID, encoding);
byte[] byte1 = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byte1.Length;
request.Timeout = 20000;
System.IO.Stream newStream = request.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
newStream.Close();
System.Threading.Thread.Sleep(1000);
response = (HttpWebResponse)request.GetResponse();
System.IO.Stream dataStream = response.GetResponseStream();
reader = new System.IO.StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
if (responseFromServer.Contains("\r"))
{
responseFromServer = responseFromServer.Substring(0, responseFromServer.IndexOf("\r"));
}
Server code:
NameValueCollection postedValues = Request.Form; // Request.Form worked locally, failed on server(count=0)
IEnumerator myEnumerator = postedValues.GetEnumerator();
try
{
foreach (string s in postedValues.AllKeys)
{
if (s == "TRIALID")
{
regcode += postedValues[s];
break;
}
}
}
catch (Exception ex)
{
Response.Clear();
Response.Write("FAILED");
this.resultMsg = "FAILED. Exception: " + ex.Message;
LogResult();
return;
}
if (string.IsNullOrEmpty(regcode))
{
Response.Write("postedvalues count=" + postedValues.Count.ToString() + ": no regcode:");
this.resultMsg ="postedvalues count=" + postedValues.Count.ToString() + ": no regcode:";
LogResult();
return;
}
In the sending application, responseFromServer is postedvalues count=0:no regcode:
So the data is posted but not "seen" on the server.
The trialUserID field used in the urlencode method is a string containing user domain name plus user name from the Environment object plus the machine name.
Answer to my own question is that the url needs to be https not http.
I converted my asp.net website to https one year ago and when I created the app that sends the posted data I assumed that since the entire website is configured to automatically redirect to https that should take care of it. Clearly, the webrequest needs the https hardcoded in the url.
Just tried to click the Accept button but that is not allowed for two days since I answered my own question.
I want to login to this website using C#:
Here is my attempt but its sending me to first page. Not returning me the next page, that should be visible after login, please help me to resolve this:
string formParams =
string.Format("mail={0}&password={1}", store#admin.com", "admin");
string cookieHeader;
WebRequest req = WebRequest.Create("http://muslimgowns.com/dashboard/login/public_login");
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string pageSource = sr.ReadToEnd();
File.AppendAllText("first.txt", pageSource);
}
string pageSource1;
string getUrl = "http://muslimgowns.com/dashboard/home";
WebRequest getRequest = WebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
WebResponse getResponse = getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
pageSource1 = sr.ReadToEnd();
File.AppendAllText("second.txt", pageSource1);
}
}
You can use Selenium WebDriver to automate the login process or any other process for that matter.
http://www.seleniumhq.org/
The basic idea is to:
1. Include Selenium Webdriver in your C# project
2. Goto to www.fastundercar.com
driver.Url = "http://www.fastundercar.com";
Find the Username, Password fields and the submit button (by Id, name or class) e.g.
IWebElement username = driver.FindElement(By.Name("ULogin$txtUserName"));
Set values for the username and password fields
Submit the button -
driver.findElement(By.id("submit")).click();
Check out the below link for reference:
http://www.seleniumhq.org/docs/03_webdriver.jsp
I have the Rest API Url https://www.box.com/api/oauth2/token. To get the Refresh/Access Tokens respectively.
When i try this in PostMan (Chrome Extension) Its working fine. Below i have attached the screen shot.
Getting the Access Token Reference : https://developers.box.com/oauth/
But the same i tried in Code its giving me the Bad Request Error.
public string PostToUrl(string url, string data)
{
string results = String.Empty;
WebRequest req = WebRequest.Create(url);
req.Method = WebRequestMethods.Http.Post;
byte[] byteArray = Encoding.UTF8.GetBytes(data);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = byteArray.Length;
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse res = req.GetResponse();
dataStream = res.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
results = reader.ReadToEnd();
return results;
}
public override void TestConnection(TimeSpan timeout)
{
string json = PostToUrl("https://www.box.com/api/oauth2/token", "code=" + Code + "&grant_type=authorization_code&client_id=" + ClientId + "&client_secret=" + ClientSecret);
}
here my question is....
How do i need to form the request for this rest API call?
How the Multi Form Data's and values need to be merged to that request?
Box Request through Post Man:
Box Request from My Code :
Try to compare both request with fiddler to catch the differences.
You can also simplify your Rest handling code with RestSharp.
I have added the NameValueCollection to the Headers. Like Below
var nameValue = new NameValueCollection
{
{"grant_type", "authorization_code"},
{"client_id", ClientId},
{"client_secret", ClientSecret},
{"code", RefreshToken}
};
request.Headers.Add(nameValue);
Initial Reference Link
Now it's working fine.
I'm trying to scrape a website that requires a login. Getting an error that I haven't received before, copied the code from another forum successfully in the past:
Exception Details: System.Net.ProtocolViolationException: Cannot send a content-body with this verb-type.
with the code:
Stream newStream = http.GetRequestStream(); //open connection
Here's the entire code:
#{
var strUserId = "userName";
var strPassword = "password";
var url = "formSubmitLandingSite";
var url2 = "pageToScrape";
HttpWebRequest http = WebRequest.Create(url) as HttpWebRequest;
http.KeepAlive = true;
http.Method = "POST";
http.ContentType = "application/x-www-form-urlencoded";
string postData = "email=" + strUserId + "&password=" + strPassword;
byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(postData);
http.ContentLength = dataBytes.Length;
using (Stream postStream = http.GetRequestStream())
{
postStream.Write(dataBytes, 0, dataBytes.Length);
}
HttpWebResponse httpResponse = http.GetResponse() as HttpWebResponse;
// Probably want to inspect the http.Headers here first
http = WebRequest.Create(url2) as HttpWebRequest;
http.CookieContainer = new CookieContainer();
http.CookieContainer.Add(httpResponse.Cookies);
HttpWebResponse httpResponse2 = http.GetResponse() as HttpWebResponse;
Stream newStream = http.GetRequestStream(); //open connection
newStream.Write(dataBytes, 0, dataBytes.Length); // Send the data.
newStream.Close();
string sourceCode;
HttpWebResponse getResponse = (HttpWebResponse)http.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
sourceCode = sr.ReadToEnd();
}
Response.Write(sourceCode);
}
You're creating a new request object here:
http = WebRequest.Create(url2) as HttpWebRequest;
Keep in mind that the default HTTP verb used is GET. Then you try to open the request stream here:
Stream newStream = http.GetRequestStream();
This method is used to enable writing data to the request's content. However, GET requests don't have content. As you do in the code above the error, you'll need to use a different HTTP verb. POST is most common for this, and is what you're using above:
http.Method = "POST";
So just use a POST request again. (Assuming, of course, that's what the server is expecting. In any event, if the server is expecting content then it's definitely not expecting a GET request.)
I am using C# (ASP.NET). I want to use Google OAuth for accessing the user profile detail in my app. I successfully got the authorization code but having a problem in getting the access token.
I prefer the Google tutorials. In tutorial, I read that I have to send the request and get the response from google. For that, I use System.Net.HttpWebRequest/HttpWebResponse (am I going in the right way). I have used this code...
byte[] buffer = Encoding.ASCII.GetBytes("?code=" + code + "&client_id=xxx&client_secret=xxx&redirect_uri=xxxx&grant_type=authorization_code");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://accounts.google.com");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = buffer.Length;
Stream strm = req.GetRequestStream();
strm.Write(buffer, 0, buffer.Length);
strm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Response.Write(((HttpWebResponse)resp).StatusDescription);
But, I got the error:
The remote server returned an error: (405) Method Not Allowed.
Update: Here variable code is authorization code.
I think you are sending the POST request to the wrong endpoint, the correct one is https://accounts.google.com/o/oauth2/token
As I had similar problems in the process of implementing Google auth, I will post the code that works.. The last mentioned problem: error (400) Bad request could be caused by leading '?' in the above code..
string codeClient = "code="+ t +"&client_id=number.apps.googleusercontent.com&";
string secretUri = "client_secret=yoursecret&" + "redirect_uri=path&"
+ "grant_type=authorization_code";
postString = codeClient + secretUri;
string url = "https://accounts.google.com/o/oauth2/token";
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(postString);
Stream os = null;
try
{
request.ContentLength = bytes.Length;
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
}
catch
{ }
try
{
HttpWebResponse webResponse = (HttpWebResponse) request.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
result = responseStreamReader.ReadToEnd();//parse token from result
My code is working, I have done mistakes in above two lines. It should be like this
byte[] buffer = Encoding.ASCII.GetBytes("code=" + code + "&client_id=xxx&client_secret=xxx&redirect_uri=xxxx&grant_type=authorization_code");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
Remaining code is correct.
The original request seems to be somewhat outdated. But I found that the Google's code examples contain lots of "Best Practices" housekeeping code that's hard to separate from the essential operations.
I recently published a document that represents all the REST operations as curl commands. It's hard to be conversant in every language, but curl seems universal. Most people know it- otherwise, it's pretty easy to grasp. In my curl examples, the -d flag indicates a POST operation. Otherwise, the parameters are appended to the URL.
http://www.tqis.com/eloquency/googlecalendar.htm
public string ReceiveTokenGmail(string code, string GoogleWebAppClientID, string GoogleWebAppClientSecret, string RedirectUrl)
{
string postString = "code=" + code + "&client_id=" + GoogleWebAppClientID + #"&client_secret=" + GoogleWebAppClientSecret + "&redirect_uri=" + RedirectUrl;
string url = "https://accounts.google.com/o/oauth2/token";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(postString);
Stream os = null;
try
{
request.ContentLength = bytes.Length;
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
}
catch
{ }
string result = "";
HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
result = responseStreamReader.ReadToEnd();
return result;
}
It was surprisingly difficult to find the correct and simple way of getting access token by auth code. (Especially because it has taken some time for me and then even with the correct code I got “invalid_grant” error because my auth code expired while searching :) )
So here is the code:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets()
{
// Use ones from "Web SDK configuration" section if you created your app in Firebase.
ClientId = "…",
ClientSecret = "…"
},
Scopes = new[] { "email" },
}
);
TokenResponse token = await flow.ExchangeCodeForTokenAsync(string.Empty, "4/…", string.Empty, CancellationToken.None);
As you can see, userId can be just empty, as well as redirectUri.
Don’t forget to add the Google.Apis.Auth Nuget package reference.