get html for current page in secure site - asp.net

I am trying to extract the html of my current page. To do it is pretty simple
private string GetHtml()
{
WebClient myClient = new WebClient();
string myPageHTML = null;
byte[] requestHTML;
// Gets the url of the page
string currentPageUrl = Request.Url.ToString();
UTF8Encoding utf8 = new UTF8Encoding();
requestHTML = myClient.DownloadData(currentPageUrl);
myPageHTML = utf8.GetString(requestHTML);
Response.Write(myPageHTML);
return myPageHTML;
}
But my problem I am having is, if this page is behind a secure section, the WebClient is effectively unauthenticated, so the server will just return the "Login screen" instead.
Can I pass my cookie or my session to this WebClient?

Related

Tableau Unexpired Trusted Ticket - including ClientIP

I have an ASP.NET web application in which I'm rendering different tableau dashboards from a site based on the menu clicked by the user. I have multiple menus and each menu was tied to a tableau URL.
Tableau Trusted Authentication has been implemented to get the trusted ticket from the tableau server. Once the ticket has been retrieved, I am appending the ticket to the dashboard URL along with the server name for each menu.
The trusted ticketing module is working fine and the visualizations are getting rendered in my web application. However, frequently I am getting a message of "Could not locate unexpired ticket" error.
On checking with this error, this is due to the ticket calls getting duplicated.
I reached out to the support regarding this and got a response that I can add client_ip during my trusted ticketing.
Tableau Trusted Ticket
I am not able to find any code article related to adding client_ip in trusted ticketing.
Below is my trusted ticket code.
public class TableauTicket
{
public string getTableauTicket(string tabserver, string sUsername)
{
try
{
ASCIIEncoding enc = new ASCIIEncoding();
string postData = string.Empty;
string resString = string.Empty;
postData = "username=" + sUsername + "";
// FEATURE 816 END - Custom Visualization - KV
if (postData != string.Empty)
{
byte[] data = enc.GetBytes(postData);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(tabserver + "/trusted");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
req.ContentLength = data.Length;
Stream outStream = req.GetRequestStream();
outStream.Write(data, 0, data.Length);
outStream.Close();
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
StreamReader inStream = new StreamReader(stream: res.GetResponseStream(), encoding: enc);
resString = inStream.ReadToEnd();
inStream.Close();
return resString;
}
else
{
resString = "User not authorised";
return resString;
}
}
catch (Exception ex)
{
string resString = "User not authorised";
return resString;
string strTrailDesc = "Exception in tableau ticket - " + ex.Message;
}
}
public int Double(int i)
{
return i * 2;
}
}
Can anyone please let me know how the client_ip can be passed in trusted ticketing code?
Also, the client IP will get changed for each user and how this will be handled in the trusted ticketing?
UPDATE
I have solved the issue using the source code provided by tableau on how to embed the view in SharePoint.
Below is the code which may help users having the same issue.
string GetTableauTicket(string tabserver, string tabuser, ref string errMsg)
{
ASCIIEncoding enc = new ASCIIEncoding();
// the client_ip parameter isn't necessary to send in the POST unless you have
// wgserver.extended_trusted_ip_checking enabled (it's disabled by default)
string postData = "username=" + tabuser + "&client_ip=" + Page.Request.UserHostAddress;
byte[] data = enc.GetBytes(postData);
try
{
string http = _tabssl ? "https://" : "http://";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(http + tabserver + "/trusted");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = data.Length;
// Write the request
Stream outStream = req.GetRequestStream();
outStream.Write(data, 0, data.Length);
outStream.Close();
// Do the request to get the response
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
StreamReader inStream = new StreamReader(res.GetResponseStream(), enc);
string resString = inStream.ReadToEnd();
inStream.Close();
return resString;
}
// if anything bad happens, copy the error string out and return a "-1" to indicate failure
catch (Exception ex)
{
errMsg = ex.ToString();
return "-1";
}
}
Assuming your code is working, (I have done this part in Java and not really an expert in asp.net) all you have to do is to add something like:
postData = postData +"&client_ip=" +<variable for client IP>;
The way it is handled on tableau server is :
you turn on wgserver.extended_trusted_ip_checking on Tableau server. see details here
Tableau will match the client IP you passed in the POST request 'client_ip=XXX.XXX.XXX.XXX' while obtaining the token, with the actual IP of the the machine where the browser is trying to access tableau server.

IIS Cross-Domain Redirection POST?

Is it possible to have an ASP.NET web proxy accept a GET request from the client, perform a POST to an external website, and then send the external POST response back to the original client in the form of a redirect (URL change in address bar)?
The client calls my proxy like this: internalWebsite.com?userId=1234.
Server-side, I then create an HttpWebRequest (POST) pointed to the external URL, take that userId query string to build a token and place it in the HttpWebRequest Authorization header, which the external site requires for authentication.
When this response comes back, I return the external HTML response string to the original client. The problem is that the HTML page has relative links to images, css, pages that do not work since the browser still thinks it is on my internal website.
I have seen many examples of doing external GET, and even external POST as long as I don't need the authorization header, but I cannot get this to work. See code below...
string url = "externalWebSite.com/login";
StringBuilder postData = new StringBuilder();
postData.Append("post data goes here");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
WebHeaderCollection myWebHeaderCollection = request.Headers;
myWebHeaderCollection.Add("Authorization", "Bearer" + " " + token);
request.Headers = myWebHeaderCollection;
request.AllowAutoRedirect = true; //new
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.ToString().Length;
//request.UseDefaultCredentials = true;
request.UserAgent = ".NET Web Proxy";
request.Referer = url;
StreamWriter writer = null;
try
{
writer = new StreamWriter(request.GetRequestStream());
writer.Write(postData.ToString());
writer.Flush();
HttpWebResponse WebResp = (HttpWebResponse)request.GetResponse();
//Now, we read the response (the string), and output it.
Stream Answer = WebResp.GetResponseStream();
StreamReader _Answer = new StreamReader(Answer);
_context.Response.ContentEncoding = Encoding.UTF8;
_context.Response.ContentType = WebResp.ContentType;
_context.Response.Write(_Answer.ReadToEnd());
}
finally
{
if (writer != null)
writer.Close();
}
Thanks in advance for your help!
After you recieve content, try to insert html-tag "base" just after "head" section begins:
<html>
<head>
<base href="http://externalWebSite.com">
... <!-- content from externalWebSite.com -->
Also, if you want to display all content that you recieved, it is better override Render method on your page:
protected override void Render(HtmlTextWriter writer)
{
string result = GetContentFromTherOtherSite();
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
base.Render(htw);
writer.Write(result);
}
In this case, on your page there will be only content from the other site, without your tags.

log in to a site programatically using C#

I want to log in to a website setting.fun-freak.com just for learning purpose by using a windows desktop application. I used webrequest and tried as
string formUrl = "http://setting.fun-freak.com/Account/Login.aspx";
string formParams = string.Format("ctl00$MainContent$txtUserName=loginId&ctl00$MainContent$txtPassword=password");
string cookieHeader;
WebRequest req = WebRequest.Create(formUrl);
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);
}
using (StreamReader sr = new StreamReader(req.GetResponse()))
{
pageSource = sr.ReadToEnd();
}
I assume that this pageSource object will have html of next page after login page (if login succesfully), but it contains the same login page in return.
How can I successfully log in to this website and get home page in response?
Moreover, this (setting.fun-freak.com) my own site, built in asp.net webforms. Here is button click event code (May be it help to dig out the problem)
UserContainer User = new UserProcessing().Authenticate(txtUserName.Text, txtPassword.Text);
if (User != null)
{
Session["User"] = User;
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, RememberMe.Checked);
}
else
{
lblMessage.Text = "Invalid credentials. Please try again";
}
Any help will be appreciated.
I added this piece of code as it is, but it still not working .
it is taken from http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
// Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create("http://setting.fun-freak.com/Account/Login.aspx");
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = "ctl00$MainContent$txtUserName=UserName&ctl00$MainContent$txtPassword=Password";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
The problem is that the object responseFromServer do not show then content of next to the login page. Its shows only login page contents.

Forward a QueryString to another Server

I have a webapp that accepts a messageid and status as a QueryString from an external server. I am migrating the webapp to a new server, but I need the new server to forward the QueryString to the old server in case the old server is still waiting for updates, and until I can get my clients migrated over.
The External website calls my webapp with ?MSGID=12345678&RESPONSE=0
eg:
http://dlrnotify.newserver.com/GetResponse.aspx?MSGID=12345678&RESPONSE=0
I need my code behind GetResponse.aspx to process the message locally, and then forward the request to the old server. eg, calling:
http://dlrnotify.oldserver.com/GetResponse.aspx?MSGID=12345678&RESPONSE=0
I don't really want to redirect the user to the old web server, just to pass the querystring on from my app.
I can get the QueryString by calling Response.QueryString.ToString() I just need to know how to post that to the old server without upsetting anything.
Sorry if this is a dumb question, I don't work with web apps very often and am obviously using the wrong search terms.
You can use HttpWebRequest and HttpWebResponse for this. Below is an example to use thses
Uri uri = new Uri("http://www.microsoft.com/default.aspx");
if(uri.Scheme = Uri.UriSchemeHttp)
{
HttpWebRequest request = HttpWebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
HttpWebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
response.Close();
Response.Write(tmp);
}
Sample Code on how to Post Data to remote Web Page using HttpWebRequest
Uri uri = new Uri("http://www.amazon.com/exec/obidos/search-handle-form/102-5194535-6807312");
string data = "field-keywords=ASP.NET 2.0";
if (uri.Scheme == Uri.UriSchemeHttp)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Post;
request.ContentLength = data.Length;
request.ContentType = "application/x-www-form-urlencoded";
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
response.Close();
Response.Write(tmp);
}
After executing your code (process message) on the new server, manually generate a HttpWebRequest which should be to your old server with the same querystring as you already figured out to form.
I have a task which is same as your post. But there is a little more in that.
As we have two web applications, one in asp.net and other in PHP. In both we create user profiles. Now the task is to Create users in Asp.NET application and we need to save the same information in PHP application from Asp.Net app.
I am using the below code for that but it is not wroking, Can you please look at it and let me know what I am missing.
CookieContainer cookies = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(#"http://localhost/admin/config/popup_user_info_brand.php");
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.CookieContainer = cookies; // note this
request.Method = "POST";
string boundary = System.Guid.NewGuid().ToString();
string Username = "admin";
string Password = "admin";
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
{
request.Credentials = new NetworkCredential(Username, Password);
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Content-Disposition: form-data; name=\"name\"");
sb.AppendLine("Singh");
sb.AppendLine("Content-Disposition: form-data; name=\"username\"");
sb.AppendLine("Singh123");
sb.AppendLine("Content-Disposition: form-data; name=\"email\"");
sb.AppendLine("a#b.com");
sb.AppendLine("Content-Disposition: form-data; name=\"password\"");
sb.AppendLine("P#ssword");
// This is sent to the Post
byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Flush();
requestStream.Close();
using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
HttpContext.Current.Response.Write(reader.ReadToEnd());
}
}
}
}
Note:- PHP web site is a 3rd party, we have no access on code.
Thanks,
Ginni.

Not able to get query string

I am using the below code for setting URL in the current http context
public HttpContext SetNewHttpContext(string uRL)
{
var httpRequest = new HttpRequest("", uRL, "");
var httpResponse = new HttpResponse(new StringWriter());
return new HttpContext(httpRequest, httpResponse);
}
Invoking it as under
HttpContext.Current = SetNewHttpContext("http://root/test.aspx?userid=319279549&name=xyz");
var val = HttpContext.Current.Request.QueryString["userid"];
But i am not able to get the value of the querystring(userid here) and getting null.
Why?
Please help
Uri tempUri = new Uri("http://root/test.aspx?userid=319279549&name=xyz");
string sQuery = tempUri.Query;
NameValueCollection queryString =
System.Web.HttpUtility.ParseQueryString(sQuery ,Encoding.UTF8);

Resources