I am using WatIn to make the login to a website. I need to get all cookies and set them to HttpWebRequest so that I will be able to download a file from this website (bank). I am using Fiddler to see all the cookies and I can see that I am missing some. If I stop my program (debug) and by hard-code insert all cookies from Fiddler to my cookie it will download my files, so that means 100% that I just need to get the cookie from WatIn and my mission is complete.
So how can I get all the cookies?
My code WaTin:
using (var browser = new IE("https://bankxxx.com"))
{
try
{
browser.WaitForComplete();
try
{
// browser.Visible = false;
browser.TextField(Find.ById("userID")).TypeText(strUser);
Thread.Sleep(1000);
browser.TextField(Find.ById("numID")).Value = strUserId;
browser.TextField(Find.ById("userPassword")).TypeText(strPass);
linkExist = browser.Image(Find.ById("inputSend")).Exists;
if (linkExist) browser.Image(Find.ById("inputSend")).Click();
browser.WaitForComplete();
linkExist = false;
}
catch (Exception ex)
{
successful = false;
clsUtils.WriteToLog("Fail to connect -" + ex.Message, true);
ErrorLog += "Fail to connect -" + ex.Message + Environment.NewLine;
}
//Here i am in side of WebSite
//I tried this too,i getting the same cookie
//CookieContainer cookies23 = browser.GetCookieContainerForUrl(new Uri("bank.com"));
//CookieCollection cookies34 = browser.GetCookiesForUrl(new Uri("bank"));
string cookies = browser.Eval("document.cookie");
CookieContainer _cookies = GeneralUtils.GetCc(cookies, "bank.com");
//then my httpreqest NOT FUll it is working 100% if cookies is good
HttpWebRequest postRequest = (HttpWebRequest)WebRequest.Create("bank.com");
postRequest.CookieContainer = new CookieContainer();
postRequest.CookieContainer = _cookies;.......
}
My GetCc function than build CookieContainer from string and add domain:
public static CookieContainer GetCc(string cookie, string Domain)
{
CookieContainer Cc = new CookieContainer();
string[] arrCookie;
string[] allcookies = cookie.Split(';');
for (int i = 0; i < allcookies.Length; i++)
{
arrCookie = allcookies[i].Split('=');
Cookie TCookie = new Cookie();
TCookie.Name = arrCookie[0].Trim().ToString();
TCookie.Value = arrCookie[1].Trim().ToString();
TCookie.Domain = Domain;
Cc.Add(TCookie);
}
return Cc;
}
Related
I am a begginer and i work in a MVC project which I cant understand it well yet.
I can't understand where does the API takes data from when I try to connect in Login Screen.
It doesn't use Entity Framework and there isn't a json with the data.
When I enter Id and Pass it calls an API (GetAPIResponse) which somehow finds that is correct.
Need help to understand the code and the logic behind it.
LoginBL class contains:
public bool IsAuthenticated(LoginEntity user)
{
string url = string.Empty;
string callType = string.Empty;
string server = string.Empty;
try
{
// get URL, Call type, Server from config file
url = ConfigurationManager.AppSettings["login_url"].ToString();
callType = ConfigurationManager.AppSettings["calltype"].ToString();
server = ConfigurationManager.AppSettings["server"].ToString();
// Encrypt password
string password = Scrambler.GenerateMD5Hash(user.Password);
// Prepare content for the POST request
string content = #"calltype=" + callType + "&server=" + server + "&user=" + user.UserName + "&pass=" + password + "";
Debug.WriteLine("Callcenter login url: " + content);
HttpResponseMessage json_list = ApiCallBL.GetAPIResponse(url, content);
LoginResponseEntity obj = new LoginResponseEntity();
obj = JsonConvert.DeserializeObject<LoginResponseEntity>(json_list.Content.ReadAsStringAsync().Result);
Debug.WriteLine(callType + " Response: " + json_list.Content.ReadAsStringAsync().Result);
//if API resultCode return 0 then user details and token save in session for further use
if (obj.ResultCode == 0)
{
int restrict = obj.UserInfo.RestrictCallType.HasValue ?
obj.UserInfo.RestrictCallType.Value : 0;
HttpContext.Current.Session["user_id"] = obj.UserInfo.usr_id;
HttpContext.Current.Session["user_name"] = obj.UserInfo.usr_username;
HttpContext.Current.Session["user_group_id"] = obj.UserInfo.UserGroupID;
HttpContext.Current.Session["groupid"] = obj.UserInfo.groupid;
HttpContext.Current.Session["token"] = obj.Token;
HttpContext.Current.Session["web_server_url"] = obj.ServerInfo.web_server_url;
HttpContext.Current.Session["centerX"] = obj.ServerInfo.DefaultGeoX;
HttpContext.Current.Session["centerY"] = obj.ServerInfo.DefaultGeoY;
HttpContext.Current.Session["dateFormat"] = obj.ServerInfo.dateFormat;
HttpContext.Current.Session["currency"] = obj.ServerInfo.currency;
HttpContext.Current.Session["customer_img"] = obj.ServerInfo.customer_img;
HttpContext.Current.Session["groups"] = obj.groups;
HttpContext.Current.Session["restrict_call_type"] = restrict ;
Debug.WriteLine("obj.UserInfo.UserGroupID " + obj.UserInfo.UserGroupID);
Debug.WriteLine("obj.UserInfo.groups " + obj.groups);
//HttpContext.Current.Session["defaultLanguage"] = obj.ServerInfo.defaultLanguage;
HttpCookie cookie = new HttpCookie("Login");
// if remember me checked then user name and password stored in cookie else cookes is expired
if (user.RememberMe)
{
cookie.Values.Add("user_name", obj.UserInfo.usr_username);
cookie.Values.Add("pwd", user.Password);
cookie.Expires = DateTime.Now.AddDays(15);
HttpContext.Current.Response.Cookies.Add(cookie);
}
else
{
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
}
return true;
}
else
{
//ResultCode -5 :Invalid Login ,-1:Database Error ,-2:Server Error ,-3:Invalid Parameter specified ,-4:Invalid Token
return false;
}
}
catch
{
throw;
}
finally
{
url = string.Empty;
callType = string.Empty;
server = string.Empty;
}
}
Okay here after converts pass to MD5 creates a "string content" with the information given.
Then in next line (HttpResponseMessage json_list = ApiCallBL.GetAPIResponse(url, content);) calls the API with the url and content as parameters where it finds if the data exists.
API code:
public static HttpResponseMessage GetAPIResponse(string url, string content)
{
StringBuilder traceLog = null;
HttpContent httpContent = null;
try
{
traceLog = new StringBuilder();
traceLog.AppendLine("Start: BusinessLayer getAPIResponse() Request Data:- " + DateTime.Now + "URL = " + url + "&content = " + httpContent);
using (HttpClient client = new HttpClient())
{
httpContent = new StringContent(content);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var resp = client.PostAsync(url, httpContent).Result;
Debug.WriteLine("resp: " + resp.Content.ReadAsStringAsync().Result);
traceLog.AppendLine("End: BusinessLayer getAPIResponse() call completed HttpResponseMessage received");
return resp;
}
}
catch
{
throw;
}
finally
{
traceLog = null;
httpContent.Dispose();
url = string.Empty;
content = string.Empty;
}
}
In the following line, console prints the result that I cant understand where it cames from (Debug.WriteLine("resp: " + resp.Content.ReadAsStringAsync().Result);)
Sorry for the confusion , I am in my first job with zero work experience and I am called to learn how this works alone without proper education on ASP.NET from them.
You will not go very far without debbugger. Learn how to debug in Visual Studio (YouTube tutorials might be fastest way). Place debug points along critical points in code (for example moment when client sends and receives response is line var resp = client.PostAsync...) and check variables.
Url for API server is actually defined in the line
url = ConfigurationManager.AppSettings["login_url"].ToString();
ConfigurationManager means Web.config file, check it's appSettings section for login_url entry, there is your url.
Btw, using (HttpClient client = new HttpClient()) is not a good way to use a HttpClient and will lead to port exhaustion. It's ok for small number of requests, but for larger ones you must reuse it, or use HttpClientFactory (for .NET Core).
I am writing some simple C# code to try automatically getting HAR file from Chrome browser. I am using browser-mob-proxy and there is a function: GetHar() which is supposed to return some different entries of URL, request and response time, etc. However, it always return me only 1 entry which is the original URL I am negativing to: www.google.com
I've tried to use dr.Navigate().Refresh() to make sure the page is reloaded so there are some activities on chrome DevTool Network section.
server.Start();
Thread.Sleep(1000);
Client client = server.CreateProxy();
client.NewHar("google");
var chromeOptions = new ChromeOptions();
var seleniumProxy = new Proxy { HttpProxy = client.SeleniumProxy };
chromeOptions.Proxy = seleniumProxy;
var dr = new ChromeDriver(chromeOptions);
dr.Navigate().GoToUrl("http://www.google.com");
dr.FindElementByClassName("gb_e").Click();
Thread.Sleep(3500);
dr.Navigate().Refresh();
// Get the performance stats
HarResult harData = client.GetHar();
Log log = harData.Log;
Entry[] entries = log.Entries;
foreach (var e in entries)
{
Request request = e.Request;
Response response = e.Response;
var url = request.Url;
var time = e.Time;
var status = response.Status;
var testStr = "Url: " + url + " - Time: " + time + " Response: " + status;
}
I expected GetHar() function will return more entries instead of only 1.
Not sure why, but the issue has been resolved by adding SSL proxy:
var seleniumProxy = new Proxy { HttpProxy = client.SeleniumProxy , SslProxy = client.SeleniumProxy };
This is how I'am saving cookie in my code which is a web service method. I tried to change the cookie expire time but still it is not working for me. Is there any issue with Context.Response to write cookie or Context.Request to read it??
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false)]
public void SaveInDraft(FormRootObject _forms)
{
HttpCookie formCookie = new HttpCookie("UserData");
formCookie.Values.Add("formid", _forms.formid);
foreach (var item in _forms.fielddata)
{
formCookie.Values.Add(item.id, item.value);
}
formCookie.Expires = DateTime.Now.AddYears(1);
Context.Response.Cookies.Add(formCookie);
}
for retrieving this cookie on next page
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false)]
public FormRootObject getDataFromCookie()
{
FormRootObject form = new FormRootObject();
List<formFielddata> lstFormFieldData = new List<formFielddata>();
var getCookie=Context.Request.Cookies["UserData"];
if (getCookie != null)
{
if (getCookie.Values.Count > 0)
{
foreach (var val in getCookie.Values)
{
formFielddata document = new formFielddata();
if (val.ToString() != "formid")
{
document.id = val.ToString();
document.value = getCookie[val.ToString()];
lstFormFieldData.Add(document);
}
else {
form.formid = getCookie[val.ToString()];
}
}
form.fielddata = lstFormFieldData;
}
}
return form;
}
but my object getCookie is always null
Rajesh, forms are only present on web applications. If you're using plain web api to create your service, no form is going to be presented to your service client.
To create a cookie:
var resp = new HttpResponseMessage();
var cookie = new CookieHeaderValue("session-id", "12345");
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return resp;
To consume cookie:
CookieHeaderValue cookie = Request.Headers.GetCookies("session-id")
I got this by storing cookies as
HttpContext.Current.Response.Cookies.Add(formCookie);
And reading this as
var getCookie=HttpContext.Current.Request.Cookies["UserData"];
I have been trying to use the .NET AWS Cloudfront API to create signed cookies for my S3 bucket, but whenever I send an HTTP request with the cookies that are created, I just get a result of "Forbidden". Is there something I am doing wrong in this code? Thanks.
CookiesForCannedPolicy cookies = AmazonCloudFrontCookieSigner.GetCookiesForCannedPolicy(
#"http://distribution123abc.cloudfront.net/*",
"KEYPAIRID",
new FileInfo(#"C:\bla\privatekey.pem"),
DateTime.Now.AddHours(1));
Uri target = new Uri(#"http://distribution123abc.cloudfront.net");
HttpWebRequest pleaseWork = (HttpWebRequest)WebRequest.Create(#"http://distribution123abc.cloudfront.net/files/test.txt");
if (pleaseWork.CookieContainer == null)
{
pleaseWork.CookieContainer = new CookieContainer();
}
pleaseWork.CookieContainer.Add(new Cookie(cookies.Signature.Key, cookies.Signature.Value) { Domain = target.Host } );
pleaseWork.CookieContainer.Add(new Cookie(cookies.KeyPairId.Key, cookies.KeyPairId.Value) { Domain = target.Host } );
pleaseWork.CookieContainer.Add(new Cookie(cookies.Expires.Key, cookies.Expires.Value) { Domain = target.Host } );
try
{
WebResponse response = pleaseWork.GetResponse();
Console.WriteLine("Response content length: " + response.ContentLength);
}
catch(WebException e)
{
Console.WriteLine(e.Message);
}
I found a solution. I had to change two things:
First I had to use signed cookies for a custom policy rather than a canned policy (and therefore use a "Policy" cookie rather than an "Expires" cookie).
Second, the domain I was setting for my cookies was incorrect. I needed to set the domain as just ".cloudfront.net", rather than specifying the domain for my distribution.
This is what my code looked like in the end:
CookiesForCustomPolicy cookies = AmazonCloudFrontCookieSigner.GetCookiesForCustomPolicy(
#"http://distribution123abc.cloudfront.net/*",
new StreamReader(#"C:\bla\privatekey.pem"),
"KEYPAIRID",
DateTime.Now.AddHours(1),
DateTime.Now.AddHours(-1),
"1.1.1.1");
string domain = ".cloudfront.net";
HttpWebRequest pleaseWork = (HttpWebRequest)WebRequest.Create(#"http://distribution123abc.cloudfront.net/files/test.txt");
if (pleaseWork.CookieContainer == null)
{
pleaseWork.CookieContainer = new CookieContainer();
}
pleaseWork.CookieContainer.Add(new Cookie(cookies.Signature.Key, cookies.Signature.Value) { Domain = domain } );
pleaseWork.CookieContainer.Add(new Cookie(cookies.KeyPairId.Key, cookies.KeyPairId.Value) { Domain = domain } );
pleaseWork.CookieContainer.Add(new Cookie(cookies.Policy.Key, cookies.Policy.Value) { Domain = domain } );
try
{
WebResponse response = pleaseWork.GetResponse();
Console.WriteLine("Response content length: " + response.ContentLength);
}
catch(WebException e)
{
Console.WriteLine(e.Message);
}
We are encountering a bit of an odd issue on our integration code with SharePoint.
We've managed to get the integration working using SAML tokens, see code below.
The problem is that sometimes it times out when getting the FedAuth cookie or making the request to SharePoint.
The timeouts might point to load or network issues but they are reproducible.
The first unit test on the unit test suite gets the cookie without any problem every single time, but it fails on the second.
To make this more mystifying, it seems to work fine whenever I have fiddler capturing traffic.
Even more annoying is the fact that if i run the second unit test and not the first, the test works fine.
It's as if SharePoint refuses to issue another cookie for the same client until a certain amount of time has passed, unless going through Fiddler.
I should add, that I have tried both storing the cookie for subsequent requests and getting it again for each request, it seems to make no difference.
Any help would be appreciated.
public static ClientContext CreateClientContext(SharePointClaimsConnection connection)
{
if (connection == null)
{
throw new ArgumentNullException("connection");
}
logger.DebugFormat("Create Client Context for connection: {0}", connection);
ClientContext context = new ClientContext(connection.WebUrl);
try
{
if (connection.SecurityTokenServiceEndPoint != null && !String.IsNullOrEmpty(connection.Realm))
{
CookieInfo token = GetToken(connection);
if (token == null)
{
lock (syncRoot)
{
token = GetToken(connection);
if (token == null)
{
token = GetFedAuthCookie(connection);
if (token != null)
{
tokens[connection] = token;
}
}
}
}
if (token != null)
{
context.ExecutingWebRequest += (s, e) =>
{
e.WebRequestExecutor.WebRequest.KeepAlive = true;
for (int i = 0; i < e.WebRequestExecutor.WebRequest.Headers.Count; i++)
{
string key = e.WebRequestExecutor.WebRequest.Headers.GetKey(i);
string value = e.WebRequestExecutor.WebRequest.Headers.Get(i);
logger.DebugFormat("Key: {0}, Value: {1}", key, value);
}
CookieContainer container = new CookieContainer();
foreach (var cookie in token.Cookies)
{
logger.Debug("Adding cookie: " + cookie.Name);
logger.Debug("Domain: " + connection.WebUrl.Host);
logger.Debug("Expires: " + cookie.Expires.ToString());
Cookie newCookie = new Cookie(cookie.Name, cookie.Value);
newCookie.Expires = DateTime.MaxValue;
newCookie.Path = "/";
newCookie.Secure = true;
newCookie.HttpOnly = true;
newCookie.Domain = connection.WebUrl.Host;
container.Add(newCookie);
}
e.WebRequestExecutor.WebRequest.CookieContainer = container;
};
}
}
return context;
}
catch (Exception ex)
{
if (context != null)
{
context.Dispose();
}
throw;
}
}
private static CookieInfo GetFedAuthCookie(SharePointClaimsConnection connection)
{
string result = GetSamlToken(connection);
//Take this token and pass it to SharePoint STS
string stringData = String.Format(CultureInfo.InvariantCulture, "wa=wsignin1.0&wctx={0}&wresult={1}",
HttpUtility.UrlEncode(new Uri(connection.WebUrl, "/_layouts/Authenticate.aspx?Source=%2F").ToString()),
HttpUtility.UrlEncode(result));
HttpWebRequest sharepointRequest = HttpWebRequest.Create(new Uri(connection.WebUrl, "/_trust/")) as HttpWebRequest;
sharepointRequest.Method = "POST";
sharepointRequest.ContentType = "application/x-www-form-urlencoded";
sharepointRequest.CookieContainer = new CookieContainer();
sharepointRequest.AllowAutoRedirect = false; // This is important
using (Stream newStream = sharepointRequest.GetRequestStream())
{
byte[] data = Encoding.UTF8.GetBytes(stringData);
newStream.Write(data, 0, data.Length);
}
HttpWebResponse webResponse = sharepointRequest.GetResponse() as HttpWebResponse;
if (webResponse.Cookies["FedAuth"] == null)
{
return null;
}
return new CookieInfo()
{
Cookies = webResponse.Cookies.Cast<Cookie>().ToList(),
};
}
private static string GetSamlToken(SharePointClaimsConnection connection)
{
string result;
Uri STSService = new Uri(connection.SecurityTokenServiceEndPoint, WindowsTransport);
using (WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(
new WindowsWSTrustBinding(SecurityMode.Transport),
new EndpointAddress(STSService)))
{
trustChannelFactory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13;
trustChannelFactory.Credentials.SupportInteractive = false;
trustChannelFactory.ConfigureChannelFactory<IWSTrustChannelContract>();
//Request Security Token
RequestSecurityToken rst = new RequestSecurityToken();
rst.KeyType = KeyTypes.Bearer;
rst.RequestType = RequestTypes.Issue;
rst.AppliesTo = new EndpointAddress(connection.Realm);
var channel = trustChannelFactory.CreateChannel();
WSTrust13RequestSerializer trustSerializer = new WSTrust13RequestSerializer();
using (Message message = Message.CreateMessage(
MessageVersion.Default, WSTrust13Constants.Actions.Issue,
new RequestBodyWriter(trustSerializer, rst)))
{
Message response2 = channel.EndIssue(channel.BeginIssue(message, null, null));
XmlDictionaryReader reader = response2.GetReaderAtBodyContents();
result = reader.ReadOuterXml();
}
}
return result;
}