1

I'm trying JSONP response by using @ControllerAdvice. But unnecessary comment appears before callback function name.

build.gradle

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.2.7.RELEASE'
}

Application

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Controller

@RestController
public class Controller {
    @ControllerAdvice
    public static class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
        public JsonpAdvice() {
            super("callback");
        }
    }

    @RequestMapping("/product")
    public Product product(@RequestParam(value = "callback", required = false) String callback) {
        return new Product(1, "foo", 100);
    }
}

Product

public class Product {
    int id;
    String name;
    int price;

    public int getId() {
        return id;
    }

    /* getters, setters, constructor */
}

Result http://localhost:8080/product?callback=callback

/**/callback({"id":1,"name":"foo","price":100});

How can I remove /**/ before callback?
Thanks.

3 Answers3

2

I came across exactly the same problem as you, and thus found your post. However, based on the Spring Boot source code:

@Override
protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
    if (this.jsonPrefix != null) {
        generator.writeRaw(this.jsonPrefix);
    }
    String jsonpFunction =
            (object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null);
    if (jsonpFunction != null) {
        generator.writeRaw("/**/");//NB! This is the added content
        generator.writeRaw(jsonpFunction + "(");
    }
} 

from https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java, where there is generator.writeRaw("/**/");, I really don't think the author added this statement by mistake, he must have added it on purpose and he does not want it to be removed at all. So curiosity motivated me to investigate this issue for several hours. The reason for adding the statement generator.writeRaw("/**/");, i.e. /**/ before jsonp callback function name, is security.

From the link https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/, it was told "To be also protected from content sniffing attacks(click to see the meaning), prepend the reflected callback with /**/. This is exactly what Google, Facebook and GitHub are currently doing."

Even Google, Facebook and GitHub are currently doing so, is there sense for us to remove the /**/? In my humble opinion, we should definitely keep it there. I did try to use the jsonp callback with prepended /**/in an html client and it can still work properly. Moreover, the jsonp callback implementation should take the other mitigation and fix sugguestions from https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ into consideration. The [Yahoo Finance REST API implementation https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22BHP.AX%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=foo is a typical example. One can read the header information with some Header reading tool to see how it is implemented on purpose of avoiding json hijacking.

Rui
  • 3,454
  • 6
  • 37
  • 70
0

@Configuration Annotation in the place where it is declared

    @Bean
public MappingJackson2HttpMessageConverter MappingJackson2HttpMessageConverter (ApplicationContext applicationContext) {
    ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().applicationContext(applicationContext).build();
    return new MappingJackson2HttpMessageConverter(objectMapper) {
        @Override
        protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
            String jsonpFunction =
                    (object instanceof MappingJacksonValue ? ((MappingJacksonValue) object).getJsonpFunction() : null);
            if (jsonpFunction != null) {
                generator.writeRaw(jsonpFunction + "(");
            }
        }

    };
}

Replace class "MappingJackson2HttpMessageConverter"

sbcoba
  • 91
  • 1
0

generator.writeRaw("/**/");//NB! This is the added content

as the code above for the security reason, actually, there is another way to do so:

generator.writeRaw("\r\n")

avoid xss attack.

Alexan
  • 8,165
  • 14
  • 74
  • 101
fatboy
  • 1