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攻击。
我正在尝试使用@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攻击。