cancel
Showing results for 
Search instead for 
Did you mean: 

FileUploader and X-CSRF-Token?

Former Member
0 Kudos

Hi,

I have a SAPUI5 FileUploader that should post the file to a (NetWeaver Gateway) OData service - which requires that the request has an X-CSRF token. How can I make this happen?

Currently, prior to starting the upload I already did a refreshSecurityToken() on the OData model. But the FileUploader does not pick up this value. How can I proceed here?

Thank you for your help!

Accepted Solutions (0)

Answers (3)

Answers (3)

Former Member
0 Kudos

Just figure out the solution, UI5 FileUploader have method to add HTTP header, following code works for me:

fileUpLoader.setSendXHR(true); //Must set to true, otherwise HTTP headers not be added

var csrfToken = //get you CSRF token

fileUpLoader.addHeaderParameter(new sap.ui.unified.FileUploaderParameter({

     name: "X-CSRF-Token", value: csrfToken

}));

See UI5 API doc for more details.

Former Member
0 Kudos

Hello,

I am using this sap.ca.ui.unified fileuploader control to upload only xml type files.

After uploading first time, if I try to upload in the same session again. I got error: CSRF token validation failed because for every POST request CSRF token should be changed.

I have used oModel.updateSecuritytoken() and refreshSecurityToken are giving the same XCRF token in the method: handlValueChange() on new file upload.

How to get new CSRF token in the same session without service request?

I am facing this issue from long time. please help me.

0 Kudos

Hi SOumya,

Regarding the X-CSSRF-TOKEN validation issue.

we have overcome this by creating a separate service for File Upload actions(Only).

In this service we have turned off the X-CSRF Token validation check on the SAP Gateway side.

please refer to the link below.

Cross-Site Request Forgery Protection - SAP Gateway Foundation (SAP_GWFND) - SAP Library

When this check is deactivated you will not have to generate a CSRF Token at all.

please do let me know if this works for you.

Kind Regards,

Vamsi.

former_member184238
Participant
0 Kudos

Hi,

When I tried with the above example code I am getting  the following error.

In console I am getting undefined i.e console.log(oRequest.headers['x-csrf-token']);

and in network tab I am getting CSRF token validation failed error.

I don't know where I have done mistake.

Help me to solve this issue.

Thanks&Regards

Sridevi

Former Member
0 Kudos

Hi Sridevi,

this example OData service that you are using does not allow changing (create, update, delete) requests.

This is probably the reason why you also get those other errors.

Regards,

Daniel

LeeG1
Product and Topic Expert
Product and Topic Expert
0 Kudos

I get the same errors....did you find a way to resolve it?

Former Member
0 Kudos

Hello,

I am using this sap.ca.ui.unified fileuploader control to upload only xml type files.

After uploading first time, if I try to upload in the same session again. I got error: CSRF token validation failed because for every POST request CSRF token should be changed.

I have used oModel.updateSecuritytoken() and refreshSecurityToken are giving the same XCRF token in the method: handlValueChange() on new file upload.

How to get new CSRF token in the same session without service request?

I am facing this issue from long time. please help me.

former_member182048
Active Contributor
0 Kudos

Hi Daniel

Further to the suggestion i made in  http://scn.sap.com/thread/3383994 that I didn't think this was possible with the FileUploader control, I found some time today to investigate further.

I tried to use a proxy to set the http headers like Jibin Joy suggested in http://scn.sap.com/thread/3262540 the issue like he found was that the data that is posted is encoded as multipart/form-data and the Gateway service is expecting a media resource with the correct content type eg image/gif.

I managed to get the FileLoader control posting successfully to Gateway services by extending the control, replacing the form.submit with an AJAX call.

sap.ui.commons.FileUploader.extend("ODataFileLoader", {

...

     upload : function() {

...

                    var file = jQuery.sap.domById("upload_1-fu").files[0];

                    var oRequest = sap.ui.getCore().getModel(this.getModelName())._createRequest();

                    var oHeaders = {

                              "x-csrf-token": oRequest.headers['x-csrf-token'],

                              "slug": this.getSlug(),

                    };

                    jQuery.ajax({

                              type: 'POST',

                              url: this.getUploadUrl(),

                              headers: oHeaders,

                              cache: false,

                              contentType: false,

                              processData: false,

                              data: file,

                              success: _handleSuccess,

                              error: _handleError

                    });

The code gets the CSRF token from a nominated Model and uses this with a Slug header that can be dynamically set.

You can find a working example at https://github.com/jasper07/sapui5bin/blob/master/ODataFileUpload.html

Cheers

John P

Former Member
0 Kudos
Hi John,
thanks for your answer. The solution works fine - in Chrome, but it fails in IE9.
IE9 cannot do this:
var file = jQuery.sap.domById(this.getId() + "-fu").files[0];
This line returns undefined. Do you have also a solution for that?
Thanks!
former_member182048
Active Contributor
0 Kudos

Hi Daniel

I didn't have the issue with domById running in IE9, the issue i did get was IE expects the contentType to be set in the jQuery Ajax call, i updated the code so it took the content type from the file, may need a better solution for this comparing file and file extension etc.

https://github.com/jasper07/sapui5bin/blob/master/ODataFileUpload.html

HtH

John P

Former Member
0 Kudos

Hi John,

the issue is not with the domById, but with the .files. I modified the code a little to demonstrate:

var file_imput = jQuery.sap.domById(this.getId() + "-fu");

console.log(file_imput); // -> [object HTMLInputElement]

console.log(file_imput.files); // -> undefined

console.log(file_imput.files[0]); //-> also undefined

var file = file_imput.files[0]; // ->  undefined

Do you have any extensions installed that make it work for you? Or might I have some to strict security issues that prevent my IE9 from working with your code (though I tested on  two maschines)?

Thanks and reagrds,

Daniel

Former Member
0 Kudos

Hi Daniel,

on IE9 it not gonna work. Because IE9 not support File/FileReader (moderner Browser needed )

Below is the explanation and a workaround solution.

http://stackoverflow.com/questions/15664069/create-file-upload-that-work-in-ie

the plugin mentioned in the following post could also help you

http://stackoverflow.com/questions/6191792/javascript-file-upload

Or let's just use Chrome or Firefox

Regards,

Hai

0 Kudos

Hi John,


We are trying approve the workflow decision by POST the HTTP request with Headers (SAP Business Workflow with SAP NetWeaver Gateway version 7.4).

HTTP POST with Headers (x-csrf-token)

we are following the SAP document  http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/509c922a-aa9a-2f10-328c-d3814560d...

Below the code we are trying the same.

var oHeaders = {};

oHeaders["x-csrf-token"] = "<?php echo $csrftoken['xcsrfToken'];?>";

oHeaders["Authorization"] = "Basic ZGV2ZWxvcGVyOm5vc2VjcmV0";

jQuery.ajax({

    type: "POST",

    url: "http://server:port/sap/opu/odata/IWWRK/WFSERVICE/ApplyDecision?workitem_id='000000072621'&dec_key='0...'",

    data: null,

    headers: oHeaders,

    success: successFunc,

    error: errorFuncDefault

});

function successFunc(data) {

    alert(data);

}

function errorFuncDefault(data) {

    alert(data + 'error');

}

We facing the below errors like Method not supported some time and Authorization failed and we tried all possible ways but no result.

Could please help me, where  we are going wrong.

Thanks in advances

Venky.

former_member191815
Participant
0 Kudos

Hi Hai,

Thanks for you tips. Unfortunately they don't work for us.

We need to support IE9, using SAPUI5 and NetWeaver Gateway. Our upload service requires 2 header parameters, which are slug and the X-CSRF. All is possible with using ajax request as stated above and works in chrome and firefox etcetera, but not in IE9. Your tips are usefull and will work with for example using an iframe (since the fileAPI is not there yet in IE9). However, we need to be able to add the headers which is not possible for an iframe. We researched also using the XHR request, but also here adding the headers doesn't work in IE9. Would you probably have other suggestions?

Unfortunately using an other browser is not an option.


Thanks!


Wim

0 Kudos

Hi Wim,

only browsers with support for XHR file upload support setting custom headers! Unfortunatel, XHR (XMLHttpRequest) file uploads is only supported from IE 10+ on. In other words: setting HTTP headers for a file upload request will not work in IE8 and IE9. I had the same issue but with IE8.

I guess you have to create some other RESTful service for the file upload outside of the Gateway. I would be glad if the SAP Gateway team would offer some information and a workaround for IE8/IE9 users!

Cheers,

Nabi

former_member191815
Participant
0 Kudos

Hi Nabi,

Thanks for your answer. We had the same findings indeed.

We managed to fix it. Since we're already having a java server for proxying in between, we managed to fix it over there. Solution: send parameters in the url, and use the servlet to add the header parameters based on the url parameters. The servlet already had the functionality of proxying but now also use it, to add the proper headers for slug and x-csrf/ x-requested-with header. This works and does add the file in the backend. However, since IE9 sends the file via an iframe as multipart/form data, it has extra header and footer data in the file in the backend. These need to be cut off in the backend ECC system. This functionality works smoothly now for IE9.

Cheers,

Wim

former_member184739
Contributor
0 Kudos

Hi wim,

Can you please share us the content in detail how you managed to succeed in IE9 ? It would be great if you can post it as a blog. Appreciate your good work.

Regards

Prabaharan

Former Member
0 Kudos

Hi John,

I have tried the below code. It seems to send data to the url but fails at rendering.

<script type="text/javascript">

jQuery.sap.declare("MyFileUploader");

  jQuery.sap.require("sap.ui.commons.FileUploader");

  sap.ui.commons.FileUploader.extend("MyFileUploader", {

  upload : function() {

  var token;

  token = fetch_XCSRF_Token();

  var oHeaders = {

  "x-csrf-token": token,

  };

  var file = jQuery.sap.domById(this.getId() + "-fu").files[0];

  try {

  if (file) {

  this._bUploading = true;

  var that = this;

  var _handleSuccess = function(data){

  that.fireUploadComplete({"response": "Success: File uploaded to entity" });

  that._bUploading = false;

  };

  var _handleError = function(data){

  var errorMsg = '';

  if (data.responseText[1]){

  errorMsg = /<message>(.*?)<\/message>/.exec(data.responseText)[1];

  }else{

  errorMsg = 'Something bad happened';

  }

  that.fireUploadComplete({"response": "Error: " + errorMsg});

  that._bUploading = false;

  };

  jQuery.ajax({

  type: 'POST',

  url: this.getUploadUrl(),

  headers: oHeaders,

  cache: false,

  contentType: file.type,

  processData: false,

  data: file,

  success: _handleSuccess,

  error: _handleError

  });

  jQuery.sap.log.info("File uploading to " + this.getUploadUrl());

  }

  } catch(oException) {

  jQuery.sap.log.error("File upload failed:\n" + oException.message);

  }

  },

renderer :{

}

});

0 Kudos

Hi Prabaharan,

I am working on a project which we have to support file upload in IE8 and IE9, we are also using the unified FileUploader control and we faced the same problem with the x-csrf token check on gateway using IE8 and IE9.  We are able to solve this problem by creating a custom request handler.  Here is our solution:

Client side (UI5 ver 1.22.4)

-----------------

- In the UI5 client, for IE8 and IE9, add the x-csrf-token and slug (if you need it) value as hidden input value to the upload form.  For newer browser (Chrome, IE10 etc.) , these values are added to the http request header.

- You can look up how to retrieve the upload form by looking at the upload method implementation for the FileUploader control in UI5 source code.

- For IE8 and IE9, set a different value (external alias defined below) for the uploadurl attribute of the fileuploader control.

Server side

------------------

The problem for IE8 and IE9 is that the default handler class (/IWFND/CL_SODATA_HTTP_HANDLER) for ICF odata node only reads the x-csrf-token from the http header and it's not possible to set http header in IE8 and IE9.  The idea is to create a custom handler to read the x-csrf-token from the post data and add it to the http request header and resume the normal request flow.

- Create a new custom handler class that implements the interface IF_HTTP_EXTENSION.  This handler will read the x-csrf-token (or whatever name you use for the hidden input field) and set it in the http request header

- Since we cannot modify the handler list for the odata node because it's sap standard, we'll add the custom handler to the handler list in our application node which we have control.  Add the default odata handler (/IWFND/CL_SODATA_HTTP_HANDLER) as the next handler in the list.

- Create an external alias for the new custom handler (e.g. customhandler).  This value is used as the value for the uploadurl attribute on fileuploader control (pre-pend and append the value with '/', e.g. /customhandler/) before setting to uploadurl attribute.

Summary

-------------------

In IE8 and IE9, the fileuploader uploadurl will point directly to the application node and our custom handler will be processed before the default odata handler.  Our custom handler reads the x-csrf-token from the post data and sets it to the http request handler thus allowing the default odata handler to read it.

Best Regards,

Andrew


0 Kudos

Hi Adhiamol,

I am using UI5 1.22.4 and I was able to upload files using the FileUploader control without extending the FileUploader control for Chrome, Safari, Firefox and IE10.  For IE8 and IE9, UI5 uses form submit instead of XMLHttpRequest and I have to overwrite fileuploader upload method to set csrf token as hidden input values.

var oFileUploader = new sap.ui.unified.FileUploader({

buttonText:i18n('BTN_BROWSE'),

name: 'fileupload',

value: '',

sendXHR: true,

useMultipart: true,

headerParameters: [

  new sap.ui.unified.FileUploaderParameter({

   name: 'x-csrf-token',

   value: app.data.mainModel.getHeaders()['x-csrf-token']

  })

],

uploadComplete: function (oEvent) {

  log(oEvent.getParameter('response'));

  me.handleCreateComplete();

}

});

oFileUploader.setUploadUrl(your gateway service url);

For IE8 and IE9, please read my reply to Prabaharan above.

Thanks,

Andrew

former_member184739
Contributor
0 Kudos

Hi Andrew,

Thanks for the help Andrew. I followed below steps as you suggested but I am experiencing few issues. I am testing from Google Chrome REST client to make sure handler classes are triggered correctly.

Could you throw some lights here?

  1. Created a Custom handler class and added logic here to retrieve Token and slug.

2.Created an External alias and added the handler. This alias will point to the OData service which will read the attachment.Assigned as shown below.

But when calling the URL only custom handler is getting called and OData service for File upload is not getting triggered.

Issue: URL should be

http://abc.com:8030/sap/opu/odata/sap/ZGW_DEMO_READ_ATTACHMENT_SRV/FileDetailSet/

But the custom handler points only to /default_host/sap/opu/odata/sap/zgw_demo_read_attachment_srv

Entity set name is missing in the above URL.(FileDetailSet) So the runtime interface (shown below) is not getting called.

Could you please tell me how to create alias by mentioning entity set name too?

Please bare me if I am making dumb questions. Thanks.

Regards

Prabaharan Asokan

0 Kudos

Hi Prabaharan,

I believe you need to make call at the end of your custom handler to perform the next step after you've read the tokens and set them in the http header.

Thanks,

Andrew

former_member184739
Contributor
0 Kudos

Hi Andrew,

Thanks for the help !

Regards

Prabaharan

former_member184739
Contributor
0 Kudos

http://scn.sap.com/community/gateway/blog/2015/04/17/uploading-attachment-from-legacy-non-html5-brow...

Hi Andree,

I have followed your idea suggested and wrote this as a separate blog post as this will be useful for the community members. Part 1 covers what we need steps need to be covered in SAP Gateway system.(Link is given above). Hopefully I will write a separate blogs to handle this from SAPUI5 and NON_SAPUI5 web applications.

Regards

Prabaharan

Former Member
0 Kudos

Hello Prabaharan,

I would like to thank you for the detailed blog that you created which tackles the step by step process on how to configure the oData for file uploading in IE9.  This approach has been followed on the server side. On the client side I successfully uploaded the file in the oData using the control in SAPUI5 which is the sap.ui.commons.FileUploader.   First I fetch the X-csrf-token and then, used this together with the slug in order to form the upload url of the control, passing the token and slug as url parameters. 

However I am having an issue in retrieving the response from the server wherein I am getting this error in the Odata Response: “Internet Explorer Cannot Display This Feed”.  I think IE9 does not support Atom version 2.0 which is the feed format of the response (IE9 supports only older versions). Did you encounter this issue and have a recommended solution? E.g. is there a server-side configuration that controls the atom version used for the response?  

Regards,

Kath

Former Member
0 Kudos

yeah . i was using 1.20 version where they dont have the params field. I upgraded the library to 1.24 and it worked

Former Member
0 Kudos

Hello Prabaharan,

Have you find a solution on how to remove the headers and footers in the file content?

Thanks

former_member184739
Contributor
0 Kudos

Hi Kathleen,

Good to know it helped you.Thanks for the comment. I am looking to create a solution in UI side and am working on this. I think we need to cut off the extra header and footer in the request and remove the file content before sending the response to caller interface(app).

Since novice to UI5 i am consuming a bit of time on this. I would appreciate your help on this if you could share me the code snippet (client side) to upload the file . Let me know your thoughts. Thanks

Regards

Prabaharan Asokan

former_member184739
Contributor
0 Kudos

Hi Andrew,

I am looking to create a solution in UI side suggested by you and am working on this.Since novice to UI5 i am consuming a bit of time on this. I would appreciate your help on this if you could share me the code snippet (client side) to upload the file . Let me know your thoughts. Thanks

Regards

Prabaharan Asokan

0 Kudos

Hi Prabaharan,

Here are the code snippets in reference to my original description for the changes needed to be made on the client side based on UI5 version 1.22.4.

*It's possible that additional changes/updates are required for the code snippets to be compatible/work in newer version of UI5.

Client side (UI5 ver 1.22.4)

-----------------

- In the UI5 client, for IE8 and IE9, add the x-csrf-token and slug (if you need it) value as hidden input value to the upload form.  For newer browser (Chrome, IE10 etc.) , these values are added to the http request header.

     Override the function sap.ui.unified.FileUploader.prototype.upload.  Since we want to keep the existing      implementation for non IE8 and non IE9 browsers,  the changes we add should only apply to IE8 and      IE9.  In this function, there should already be a check for 'window.File'.   We'll add the following code to      set the header parameters as hidden input fields to the form when 'window.File' returns false. 

     if (this.getSendXHR() && window.File) {

         ....

     }

     else {

     if (sap.ui.Device.browser.msie && (sap.ui.Device.browser.version==8           || sap.ui.Device.browser.version==9)) {

          if (this.getHeaderParameters()) {

            var oHeaderParams = this.getHeaderParameters();

            for (var i = 0; i < oHeaderParams.length; i++) {

                 var sHeader = oHeaderParams[i].getName();

                 var sValue = oHeaderParams[i].getValue();

                 if(sHeader=='x-csrf-token' || sHeader=='slug'){

                      var el = document.createElement('input');

                      el.type = 'hidden';

                      el.name = sHeader;

                      el.value = sValue;

                      uploadForm.appendChild(el);

                 }

            }

         }

     }

     uploadForm.submit();

   }

- You can look up how to retrieve the upload form by looking at the upload method implementation for the FileUploader control in UI5 source code.

     The uploadForm should already be available in the overridden method (see above).

- For IE8 and IE9, set a different value (external alias defined below) for the uploadurl attribute of the fileuploader control.

     // Call updateSecurityToken() from your model

     var oFileUploader = new sap.ui.unified.FileUploader({

          ...     

        sendXHR: true,

        useMultipart: true,

        headerParameters: [

        new sap.ui.unified.FileUploaderParameter({

            name: 'x-csrf-token',

            value: your csrf token value

        }),

        // if you need 'slug'

        new sap.ui.unified.FileUploaderParameter({

            name: 'slug',

            value: your slug value

        })

        ]

     })

     oFileUploader.setUploadUrl(url);

     // For IE8 and IE9, the url value would be the external alias of your custom handler

     // For all other browser, it will be your default service url for file upload

Thanks,

Andrew