on 04-13-2015 8:37 AM
Greetings All
We are trying to make a POST/PUT request from C# .NET 3.5 client application to SAP Netweaver Gateway;
Background:
- Are there any other additional http request parameters required to succesfuly submit a POST or a PUT to SAP Netweaver Gateway.
- Are there any other additional settings from a transaction level that we have to set up to make this service call from external client source.
Please see the following code:
private void CheckCrossSiteForgeryToken()
{
Cursor.Current = Cursors.WaitCursor;
string _UrlToInvoke= "https://xxxxxxxxxxx:4430/sap/opu/odata/SAP/ZTEST_PROJECT_SRV_01/ZTEST_PROJECTSet";
HttpWebResponse httpWebResponse = null;
try
{
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(UrlToInvoke);
httpRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
httpRequest.Method = "GET";
httpRequest.KeepAlive = true;
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";
httpRequest.AllowAutoRedirect = true;
httpRequest.Credentials = new NetworkCredential(txtUID.Text, txtpwd.Text);
httpRequest.KeepAlive = true;
httpRequest.Headers.Add("X-CSRF-Token", "Fetch");
HttpWebResponse resp = (HttpWebResponse)httpRequest.GetResponse();
// Assign values from response to class variables.
gcsrfToken = resp.Headers.Get("X-CSRF-Token");
gsetCookie = resp.Headers.Get("Set-Cookie");
Stream responseStream = resp.GetResponseStream();
}
catch (WebException error)
{
rtOutput.Text = "Error encountered: " + error.ToString();
}
Cursor.Current = Cursors.Default;
}
The above function authenticates the user and pwd succesfully and returns the relevant Token and Cookie, with no issues..!
private void PostDataTOSAPGateway()
{
Cursor.Current = Cursors.WaitCursor;
string _UnloadReportEventURL1 = "https://xxxxxxxxxxx:4430/sap/opu/odata/SAP/ZTEST_PROJECT_SRV_01/ZTEST_PROJECTSet";
HttpWebResponse httpWebResponse = null;
try
{
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(UrlToInvoke);
httpRequest.Accept = "application/xml,application/atom+xml";
httpRequest.Method = "PUT";
httpRequest.ProtocolVersion = HttpVersion.Version11;
httpRequest.AllowWriteStreamBuffering = true;
httpRequest.KeepAlive = true;
//httpRequest.ContentType = "application/x-www-form-urlencoded";
//request.ContentType = "application/json; charset=utf-8";
httpRequest.ContentType = "application/atom+xml";
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";//"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Mobile/7D11";
httpRequest.AllowAutoRedirect = true;
httpRequest.Credentials = new NetworkCredential(txtUID.Text, txtpwd.Text);
httpRequest.KeepAlive = true;
//set the Token
httpRequest.Headers.Add("X-CSRF-Token", gcsrfToken);
//set the cookie
httpRequest.Headers.Add("Set-Cookie", gsetCookie);
//check the header is applied before sending
gcsrfToken = httpRequest.Headers.Get("X-CSRF-Token");
String fileName = "Test XML.txt";
//String fileName = "Event_single.txt";
string sDir = "C:\\TestData\\";
// Read the data.
StreamReader streamData = new StreamReader(sDir + fileName); //StreamReader(Application.StartupPath + @"/Resources/" + fileName + ".txt"))
//obtain the data to submit
String sxml = streamData.ReadToEnd();
streamData.Close();
streamData.Dispose();
byte[] bytedata = Encoding.UTF8.GetBytes(sxml);
httpRequest.ContentLength = bytedata.Length;
using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
{
streamWriter.Write(sxml);
streamWriter.Flush();
}
The HTTP Web exception occurs when we try to obtain the response from the above PUT the following:
the exception is HTTP 403.
try
{
httpWebResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch (WebException ex)
{
MessageBox.Show("Exception: " + ex.Message + " " + ex.Response + " status:" + ex.Status + " target:" + ex.TargetSite + " source:" + ex.Source);
}
}
catch (WebException error)
{
rtOutput.Text = "Error encountered: " + error.ToString();
}
Cursor.Current = Cursors.Default;
}
THE DATA WE ARE Submitting:
<?xml version="1.0" encoding="UTF-8"?><atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><atom:content type="application/xml"><m:properties><d:Mandt>022</d:Mandt><d:Pernr>10000000</d:Pernr></m:properties></atom:content></atom:entry>
The HTTP Web exception occurs on the following:
try
{
httpWebResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch (WebException ex)
{
MessageBox.Show("Exception: " + ex.Message + " " + ex.Response + " status:" + ex.Status + " target:" + ex.TargetSite + " source:" + ex.Source);
}
If anyone has succesfully integrated a PUT/POST to SAP Netweaver using .net framework c#, please provide some input on the above mentioned issues.
Thank you and I look forward to your responses.
Kind regards,
--Edwin Ramos
Hi you may try storing your session cookies.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi you may try storing your session cookies.
Would you post your code to do this ? I am having the exact same issue (see https://scn.sap.com/thread/3956649)
I followed a couple of other posts that describe saving cookies to fix this issue but they did different (and incompatible) things and neither worked for me.
Martin
Hi Gaurav,
Good suggestion,
We are reaching SAP NWG because if a wrong UID and PWD is sent
we get a http 401 unauthorised.
The test code is executed within internal machine and not going through DMZ.
I will check the internal web dispatcher if this is filter a POST request, but not sure if this is applicable.
Any other suggestions are welcomed.
Thanks once again.
Kind regards,
--Edwin
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Guarav,
We have turned on the traces. Great! thank you for this pointer.
The HTTP 403 as mentioned based on the log:
CSRF validation failed for the user, which is confusing because we are definitely setting the header
prior to making the http web request:
See below:-
//set the Token
httpRequest.Headers.Add("X-CSRF-Token", gcsrfToken);
//set the cookie
httpRequest.Headers.Add("Set-Cookie", gsetCookie);
//check the header is applied before sending
gcsrfToken = httpRequest.Headers.Get("X-CSRF-Token");
Is there anyway know what the payload or http header received by the server.
Fiddler would be good to run but unable to install this on machine due to security.
regards,
Edwin
Hi Guarav,
Our Basis team did the system tracing and have checked the payload received by SAP NG;
1. confirm that the same X-CSRF-Token values are the same from the GET response and the POST request.
2. we added a HTTP header parameter
“X-Requested-With=XMLHttpRequest “
and then disable check_csrf_token in SICF
and still get a HTTP 403 response- the trace comes back with CSRF validation failed.
Such a painful experience and I am sure someone has come across this issue before and managed to fully resolve.
Do you have any more suggestions.
regards,
Edwin
Hi Edwin,
Check whether the CSRF Token validation is suppressed to the service in SICF
Cross-Site Request Forgery Protection - SAP NetWeaver Gateway Foundation (SAP_GWFND) - SAP Library
Go through this link and check whether the token validation mechanism in sap has bee successfully activated
Regards
Gaurav Ahluwalia
Hi Edwin,
Follow the following
1) Retrieve a CSRF token with a non-modifying request
field X-CSRF-Token. This happens in a non-modifying request (such as GET) if the header field X-CSRF-Tokenwith the value Fetch
2)
Modify the request without CSRF token
For all modifying requests the application must include this token in an HTTP request header field with the same name ( X-CSRF-Token). The framework checks for all modifying requests the validity of the CSRF token in the request. The validation is done by the ICF runtime that checks against the token from the "anti-XSRF cookie". If the validation fails an HTTP status code 403 (Forbidden) is sent back.
for this login/ticket_only_by_https is set to 0 By setting the value of this profile parameter to 0, you can enable the use of cookies for HTTP.
SAP NetWeaver Gateway offers two CSRF protection mechanisms
3) Changing the Default CSRF Protection Mechanism
4) Compatiblity Mode for SP02 - HTTP Handler in SICF (node sdata)
( Default : X-Requested-With, to enable XSRF check use, ~CHECK_CSRF_TOKEN=1)
The request handler is /IWFND/CL_SDATA_ODATA_APP.
Standard Mode - HTTP Handler in SICF (node odata)
( Default: XSRF check, to disable and switch to X-Requested-With, use~CHECK_CSRF_TOKEN=0) The request handler is /IWFND/CL_SODATA_HTTP_HANDLER.
Regards
Gaurav Ahluwalia
Hi Edwin
Check X-CSRF Token Validation which is Cross Site Forgery Protection
Best to post a document with X-CSRF Token is to query the ODATA service document
and in the header of Request and send X-CSRF-Token : fetch in the header and use the token to post
see this URL
HTTP header X-CSRF-Token value as fetch
CSRF Protection - Connectivity - SAP Library
Using the CSRF Token - SAP Mobile Documents - SAP Library
Regards
Gaurav Ahluwalia
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Gaurav,
Good response but we know that have a value coming back from the GET request for X-CSRF Token and 100% certain we set the same value received to the http header using http header.add.
I am also explicity printing out the values to make sure it matches the same as what the get function has received.
best regards,
-Edwin
User | Count |
---|---|
87 | |
10 | |
10 | |
9 | |
7 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.