Spring 引导:删除 JSONP 回调函数名称前的 /**/

Spring Boot: Remove /**/ before JSONP callback function name

我正在尝试使用@ControllerAdvice 进行JSONP 响应。但是回调函数名前出现了不必要的注释。

build.gradle

apply plugin: 'java'

repositories {
    mavenCentral()
}

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

申请

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

控制器

@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);
    }
}

产品

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

    public int getId() {
        return id;
    }

    /* getters, setters, constructor */
}

结果http://localhost:8080/product?callback=callback

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

如何在回调前删除/**/?
谢谢。

@Configuration注解在声明的地方

    @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 + "(");
            }
        }

    };
}

替换class"MappingJackson2HttpMessageConverter"

我遇到了和你完全一样的问题,因此找到了你的post。但是,基于Spring Boot源代码:

@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 + "(");
    }
} 

来自 https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java, 哪里有generator.writeRaw("/**/");,我真的不认为作者误加了这条语句,他一定是故意加的,根本不想去掉。所以好奇心促使我调查这个问题几个小时。 之所以在jsonp回调函数名前添加语句generator.writeRaw("/**/");,即/**/,是为了安全.

在 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) 中,在反映的回调前面加上 /**/。这正是 Google、Facebook 和 GitHub 目前正在做的事情。"

甚至 Google、Facebook 和 GitHub 目前都在这样做,我们删除 /**/ 是否有意义?以我的愚见,我们绝对应该把它留在那里。我确实尝试在 html 客户端中使用带有前缀 /**/ 的 jsonp 回调,它仍然可以正常工作。此外,jsonp 回调实现应考虑其他缓解措施并修复来自 https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ 的建议。 [Yahoo Finance REST API 实现 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 就是一个典型的例子。可以用一些 Header 阅读工具来读取 Header 信息,看看它是如何实现的,目的是避免 json 劫持。

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

如上代码出于安全考虑,其实还有另一种方法:

generator.writeRaw("\r\n")

避免xss攻击。