I have created a basic CRUD API using Dropwizard and Spring. In the body of my response object, I am receiving the following:
)]}',
{
"id":10,
"initiator":2,
"target":1,
"statusId":1,
"created":"2018-04-30T14:45:01.173"
}
I checked the API using curl, postman, and programatically during testing with rest assured, and the invalid characters )]}', are always present. Postman seems to be capable of ignoring them and displaying a pretty printed output, however rest assured, and I'm guessing most JSON parsers, can't parse it correctly.
Questions:
What are they?
Why are they present?
How do I remove them?
I've been writing REST APIs for years and I've never seen anything like this. This is my first time using dropwizard so I'm optimistically hoping it is some configuration I have missed.
Apart from the the invalid characters, functionally the API works fine.
This is an inherited codebase, and other APIs return these characters also. For the purposes of testing in rest assured the invalid characters are filtered out before processing the response. While this seems acceptable to me as a workaround in the short term, long term any future consumers of the API will all have to perform the workaround, and ideally this would be fixed in the API itself.
Not aware of DropWizard but it is there to prevent json-hijacking.
In Spring there is a MappingJackson2HttpMessageConverter class.
which has same feature, but prefix is different "{} &&"
/**
* Indicate whether the JSON output by this view should be prefixed with "{} &&". Default is false.
* <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.
* The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
* This prefix does not affect the evaluation of JSON, but if JSON validation is performed on the
* string, the prefix would need to be ignored.
*/
public void setPrefixJson(boolean prefixJson) {
this.prefixJson = prefixJson;
}
You can relate to this.
Edit 1:
Spring version 4.2.0.RELEASE onwards, default prefix has been updated to )]}',
Related
I use Java (with Quarkus) for the backend.
Vue3 for the frontend.
API and Websockets to transition data between the two.
I am building a chat message application.
So far I was able to send a message inside the backend under a JSON format, do stuff in Java with this message (which holds the message inside a MessageJson class that I have created, hence the data type is now type of MessageJson), transform it into a String, then and send it back to the frontend. I wish to transform the String in the frontend, into a Json.
Here is my function which send the message back to the front (using Websockets):
public MessageResponseForm processBackend(MessageJson messageJson) {
MessageResponseForm messageResponseForm = new MessageResponseForm();
messages(messageJson);
webSocketConfig.sendMessage("U001", messageJson.toString());
return messageResponseForm;
}
The frontend retrieve it without issue, in the String format.
But I need it back into Json format.
I use the function JSON.parse() in Vue.js but it gives me this:
Which is normal in my opinion, because I should receive something like this from the backend:
"{"toRecipient":"U002","fromSender":"U00555","messageContent":"ewww555"}" .....
But instead I got this:
"MessageJson(toRecipient=U002, fromSender=U00555, messageContent=ewww555, dateCreated=2022-9-23 14:15:57, companyName=test)"
My Class MessageJson does not seems to keep the correct Json format.
How to prevent this?
Do I need to use the #Produces annotations in Quarkus? If yes, where exactly?
I found no other method related to ToString()...
EDIT: Do I need to use the dependency GSON to do the job, or can I do this natively?
I'm currently writing a Java Spring Boot application with a REST API server. I'm cutting out a lot of non-relevant code here, but one of my POST routes looks like this:
#RequestMapping(value = "/post-request", method = RequestMethod.POST)
public String postRequest(
#RequestParam(name = REQUEST_STRING) String requestString,
){ logger.info(requestString)}
This approach works great for most strings, but I'm getting a really weird error when including special characters in the request parameter. For example, if I send the application with a request containing
This (&) is an ampersand
within Postman, the application will log
This (
and cut out everything else after the special character. I'm fairly certain that this has to do with the way that special characters are encoded within REST API's, especially when it comes to request parameters, but what am I doing wrong here? Is there a way for me to get the full string using Java Spring Boot, or am I restricted from doing this?
RequestParam are diffrentiated with "&" so if you pass "&" directly in string anything after & will be treated as another RequestParam
eg:
http://testdata.com?username=test&password=hello&123&type=user
Here password will be passed as hello and 123 will be treated as anotehr RequestParam
To overcome this you need to do encoding for "&" as "%26"
http://testdata.com?username=test&password=hello%26123&type=user
I saw the following comment in Spring JSON messageConverter:
/**
* Indicate whether the JSON output by this view should be prefixed with "{} &&". Default is false.
* <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.
* The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
* This prefix does not affect the evaluation of JSON, but if JSON validation is performed on the
* string, the prefix would need to be ignored.
*/
How does string prefixing work to prevent JSON hijacks?
Contrived example: say Google has a URL like mail.google.com/json?action=inbox which returns the first 50 messages of your inbox in JSON format. Evil websites on other domains can't make AJAX requests to get this data due to the same-origin policy, but they can include the URL via a tag. The URL is visited with your cookies, and by overriding the global array constructor or accessor methods they can have a method called whenever an object (array or hash) attribute is set, allowing them to read the JSON content.
The {} && prevents this: an AJAX request at mail.google.com will have full access to the text content, and can strip it away. But a tag insertion blindly executes the JavaScript without any processing. Since {} is a falsey value the actual response would never be parsed
Other frameworks add different content to the response, like while(1); (example from Google) which causes an infinite loop for a hacker, but we can strip it out on our own site
The addition of the prefix will invalidate the string.
I think you may want to check this Stackoverflow question and comments to it:
Difference between ")]}',\n" and "{} &&" in avoiding json hijacking
I asked something like this previously, but upon re-reading my original post, it was not easy to understand what I was really asking. I have the following situation. We have (or at least I'm trying to get working) a custom file upload procedure that will take in the file, a set number of 'known' metadata values (and they will always be there), as well as potentially an unknown number of additional metadata values. The service that exists currently uses the Jersey framework (1.16)
I currently have both client and server code that handles dealing with the file upload portion and the known metadata values (server code below)
#POST
#Path("asset/{obfuscatedValue0}/")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public UUID uploadBlob(#PathParam("obfuscatedValue0") Integer obfuscatedValue0,
#FormDataParam("obfuscatedValue1") String obfuscatedValue1,
#FormDataParam("obfuscatedValue2") String obfuscatedValue2,
#FormDataParam("obfuscatedValue3") String obfuscatedValue3,
#FormDataParam("obfuscatedValue4") String obfuscatedValue4,
#FormDataParam("obfuscatedValue5") String obfuscatedValue5,
#FormDataParam("file") InputStream uploadedInputStream) {
.....
}
...and excerpt of client code:
Builder requestBuilder = _storageService
.path("asset")
.path(obfuscatedValue0.toString())
.type(MediaType.MULTIPART_FORM_DATA)
.accept(MediaType.APPLICATION_JSON);
FormDataMultiPart part = new FormDataMultiPart()
.field("file", is, MediaType.TEXT_PLAIN_TYPE) // 'is' is an inputstream from earlier in code.
.field("obfuscatedValue1", obfuscatedValue1)
.field("obfuscatedValue2", obfuscatedValue2)
.field("obfuscatedValue3", obfuscatedValue3)
.field("obfuscatedValue4", obfuscatedValue4)
.field("obfuscatedValue5", obfuscatedValue5);
storedAsset = requestBuilder.post(UUID.class, part);
However, I need to pass a map of additional parameters that will have an unknown number of values/names. From what I've seen, there is no easy way to do this using the FormDataParam annotation like my previous example.
Based upon various internet searches related to Jersey file uploads, I've attempted to convert it to use MultivaluedMap with the content type set to "application/x-www-form-urlencoded" so it resembles this:
#POST
#Path("asset/{value}/")
#Consumes("application/x-www-form-urlencoded")
public UUID uploadBlob(#PathParam(value), MultivaluedMap<String,String> formParams) {
....
}
It's my understanding that MultivaluedMap is intended to obtain a general map of form parameters (and as such, cannot play nicely together in the same method bearing #FormDataParam annotations.) If I can pass all this information from the Client inside some sort of map, I think I can figure out how to handle parsing the map to grab and 'doMagic()' on the data to get what I want done; I don't think I'll have a problem there.
What I AM fairly confused about is how to format the request client-side code when using this second method within the jersey framework. Can anyone provide some guidance for the situation, or some suggestions on how to proceed? I'm considering trying the solution proposed here and developing a custom xml adapter to deal with this situation, and sending xml instead of multipart-form-data but I'm still confused how this would interact with the InputStream value that will need to be passed. It appears the examples with MultivaluedMap that I've seen only deal with String data.
Is it possible to manipulate a SOAP message generated by Jax-WS as a String before sending it to the server? I would like to intercept the message exactly before it's going to be sent and modify some tags.
I want to do this because I need to send a SOAP request to the server. A tag of this request has a lot of xml documents as its content. For each document I need to redeclare the namespace in some tags (Jax-WS intelligently declare it just once). I can't use any prefixes. I need to sign the xml too. All these problems would be easier to solve if I could manipulate the message as a string.
I've seen something similar with axis, but I didn't find out how to do this with Jax-WS.
Thank you.
Update: I already have tried to use handlers (both SOAP and Logical handlers). My problem is that the message is changed by Jax-WS even after I modify it with the handlers. The body of my soap message needs to look like this:
<soap12:Body>
<cteDadosMsg xmlns="http://www.portalfiscal.inf.br/cte/wsdl/CteRecepcao">
<enviCTe xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
<idLote>1</idLote>
<CTe xmlns="http://www.portalfiscal.inf.br/cte">
</CTe>
<CTe xmlns="http://www.portalfiscal.inf.br/cte">
</CTe>
</enviCTe>
</cteDadosMsg>
</soap12:Body>
Look that my CTe tags need to repeat the namespace declaration (the same used by enviCTe). I tried to do the following steps:
1) Created the document containing the enviCTe using Jaxb.
2) Converted it to string and adjusted the namespace declaration of the CTe tags (using String.replace).
3) Added the xml string to the cteDadosMsg. Jax-WS escapes the characters (replacing < for < for example). The web service does not understand the xml with the escaped characters.
4) Added a LogicalHandler for unescaping the payload (replacing < for < and so on).
5) After doing this, Jax-WS adjusts the namespace declaration again and the xmlns attribute of my CTe tags disappear. :P That's my problem. Jax-WS "fix" the message even after modifying it with the handlers.
Instead of adding the xml generated by Jaxb as a string, I also tried to add it as a Document. I don't have the problems with escaping, but I still can't repeat the namespace declaration for every CTe tag.
When I solve this, I still will have to sign some tags of the xml. So I really would like to intercept the message just before it is sent and modify it as a string.
Am I missing something?
You can do the same using Handlers. Refer here for more details.