I am trying to access a webpage on a same domain / same asp.net application, that is password protected. Credentials are the same both for webpage firing this call and webpage being accessed.
Here is the code, and I don't know why I always end up with a login form html code?
using (WebClient client = new WebClient())
{
client.QueryString.Add("ID", "1040"); //add parameters
//client.Credentials = CredentialCache.DefaultCredentials;
//I tried to add credentials like this
client.Credentials = new NetworkCredential("username", "password");
string htmlCode = client.DownloadString("http://domain.loc/testpage.aspx");
}
I suspect that the web page that you are trying to access uses Forms Authentication. This means that you will have to provide a valid authentication cookie if you want to be able to access protected resources. And in order to obtain a valid authentication cookie you will have to first authenticate yourself by sending a POST request to the LogOn page which emits the cookie. Once you retrieve the cookie you will be able to send it along on subsequent requests on protected resources. You should also note that out of the box WebClient doesn't support cookies. For this reason you could write a custom cookie aware web client:
public class CookieAwareWebClient : WebClient
{
public CookieAwareWebClient()
{
CookieContainer = new CookieContainer();
}
public CookieContainer CookieContainer { get; private set; }
protected override WebRequest GetWebRequest(Uri address)
{
var request = (HttpWebRequest)base.GetWebRequest(address);
request.CookieContainer = CookieContainer;
return request;
}
}
Now you could use this client to fire off the 2 requests:
using (var client = new CookieAwareWebClient())
{
var values = new NameValueCollection
{
{ "username", "john" },
{ "password", "secret" },
};
client.UploadValues("http://domain.loc/logon.aspx", values);
// If the previous call succeeded we now have a valid authentication cookie
// so we could download the protected page
string result = client.DownloadString("http://domain.loc/testpage.aspx");
}
Obviously due to the ViewState crapiness of ASP.NET you might need to send a couple of other parameters along your logon request. Here's what you could do: authenticate in a web browser and look with FireBug the exact parameters and headers that need to be sent.
Related
I am creating an application for data retrieval from the web page. The page is password protected and when the user logs in the cookie is created.
In order to retrieve the data the application first has to log in: make web request with username and password and store the cookie. Then when the cookie is stored it has to be added into the headers of all requests.
Here is the method which makes requests and retrieves the content:
public void getAsyncDailyPDPContextActivationDeactivation()
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(dailyPDPContextActivationDeactivation);
IAsyncResult asyncResult = httpWebRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult))
using (StreamReader responseStreamReader = new StreamReader(httpWebResponse.GetResponseStream()))
{
string responseText = responseStreamReader.ReadToEnd();
}
}
Does anyone know how to modify this method in order to add a cookie into the header?
I would be also thankful if anyone suggested a way to store cookie from the response (when the application makes a request http:xxx.xxx.xxx/login?username=xxx&password=xxx the cookie is created and has to be stored for future requests).
CookieContainer cookieContainer = new CookieContainer();
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(...);
httpWebRequest.CookieContainer = cookieContainer;
Then you reuse this CookieContainer in subsequent requests:
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(...);
httpWebRequest2.CookieContainer = cookieContainer;
Use the CookieContainer or you could use a CookieAwareWebClient
My Code:
class MyWebClient : 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;
}
}
using (var client = new MyWebClient())
{
var data = new NameValueCollection
{
{ "username", "myUser" },
{ "password", "myPw" }
};
client.UploadValues("http://www..tv/takelogin.php", data);
}
MNM3.4:
Response:
Building my app i use 3 sites.. with 2 of them everything works fine but with this no.
Passing a CookieContainer usually does the trick but you're already sending it. Can you confirm the field names?
Also, for some websites, you'll need to post back the hidden fields. I usually perform a GET to the login page and, using an HTML parser (like HtmlAgilityPack), I locate the appropriate form and POST the login request with all INPUT/SELECT fields I find.
I think the best advice here is to use a debugging proxy like Fiddler and try to perform the login from the browser and inspect the generated traffic.
I Found the problem...
client.UploadValues("http://www..tv/takelogin.php", data);
changed to:
client.UploadValues("http://.tv/takelogin.php", data);
That means:
http://www.MY_SITE.tv
dont work, but
http://MY_SITE.tv
works fine.
I'm trying to send a POST request to an API controller that sets an authentication cookie. I need to retrieve that cookie, but I'm not sure how. What I have:
Sending, from a service:
public static Cookie Authenticate(string username, string url) {
using (var client = new WebClient()) {
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
var data = "="+username;
var test = client.UploadString(url, "POST", data);
// get cookie here, converted from HttpCookie
return new Cookie();
}
}
Receiving, on API Controller:
[Route("api/auth")]
[System.Web.Http.AcceptVerbs("POST")]
public HttpCookie SetCookie([FromBody] string username) {
FormsAuthentication.SetAuthCookie(username, true);
return FormsAuthentication.GetAuthCookie(decrypted, true);
}
Currently, this returns what I believe is a string representation of the cookie, which doesn't do me much good. How can I capture the HttpCookie from the WebClient?
WebClient is a high level abstraction that doesn't expose cookies to the consumer.
You have two options:
You can derive your own class from WebClient, override the GetWebResponse method and read the cookies at that point
Or you can just use lower level classes like HttpWebRequest directly.
I want to log in to my Drupal site via a C# application and have been using OAuth and Services with no success. Is there a way to log in with a session from C#? I need to do this to access my private files on my Drupal site.
I tried to use the code below from a user here on stackoverflow with now success. I get 403 when using the code.
public class CookieAwareWebClient : WebClient
{
private CookieContainer cookie = new CookieContainer();
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = cookie;
}
return request;
}
}
var client = new CookieAwareWebClient();
client.BaseAddress = #"https://www.mysite.com/";
var loginData = new NameValueCollection();
loginData.Add("login", user);
loginData.Add("password", password);
client.UploadValues("login.php", "POST", loginData); // ERROR HERE
//Now you are logged in and can request pages
string htmlSource = client.DownloadString("index.php");
There is no login.php in drupal. I think you need to check these examples: (RPC / Services 3)
https://drupal.org/node/308629
http://www.technogumbo.com/2012/05/Drupal-7-Services-3-REST-Server-C-Sharp-Example/
I am using a web service that requires authentication from .NET (Visual Studio 2010). According to the documentation, you first request a session identifier from the first web service. I can do that with no problem. Then you are supposed to call the second web service for actually performing your query, passing the session identifier in a cookie. Here is my sample code:
AuthenticateService authenticate_service = new AuthenticateService();
string session_identifier = authenticate_service.Authenticate();
SearchService search_service = new SearchService();
search_service.CookieContainer = new CookieContainer();
Cookie cookie = new Cookie("Cookie", "SID=" + session_identifier, null, search_service.Url);
search_service.CookieContainer.Add(cookie);
search_service.Test();
However, I am getting the following exception on the last line:
System.Web.Services.Protocols.SoapException was unhandled
Message=Session ID cookie value cannot be null or empty string - It is required that the high level Web service client program participate in the session initialized by the server.
Does anybody know how to properly send a cookie with a session ID to a web service?
Just figured it out...
It all had to do with the domain parameter of the Cookie constructor. I was passing search_service.Url because I wasn't sure what it was supposed to be. Apparently it should have been something like "search.google.com". When I passed that to the constructor instead, everything started working as expected.
I found this somewhere along the line. It is a cookie-aware web-client that I have been using. This allows me to have the ease of use of WebClient and pass cookies.
public class CookieAwareWebClient : WebClient
{
private CookieContainer m_container = new CookieContainer();
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = m_container;
}
return request;
}
}
Then you can just use the WebClient methods and the cookie is passed automatically after you authenticate.
Example code:
CookieAwareWebClient webClient = new CookieAwareWebClient();
NameValueCollection data = new System.Collections.Specialized.NameValueCollection();
data["user"] = "myusername"; //now holds a user=username map
byte[] response = webClient.UploadValues("http://localhost:8080/somewebservice/auth/","POST", data); //point to the webservice authentication URI
Now you can use webclient.UploadFile or UploadValues or whatever you want assuming that the previous authentication was OK.