Spring Boot:在 JSONP 回调函数名称之前删除 /**/

Posted

技术标签:

【中文标题】Spring Boot:在 JSONP 回调函数名称之前删除 /**/【英文标题】:Spring Boot: Remove /**/ before JSONP callback function name 【发布时间】:2016-02-09 16:10:00 【问题描述】:

我正在使用 @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);

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

【问题讨论】:

【参考方案1】:

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

出于安全原因,如上面的代码,实际上还有另一种方法:

generator.writeRaw("\r\n")

避免 xss 攻击。

【讨论】:

【参考方案2】:

我遇到了和你完全相同的问题,因此找到了你的帖子。但是,基于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("/**/");语句,即/**/的原因是安全

从链接https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/,它被告知“为了防止content sniffing attacks(click to see the meaning),在反射回调前加上/**/。这正是谷歌、Facebook和GitHub目前正在做的事情。”

即使是谷歌、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劫持。

【讨论】:

【参考方案3】:

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

    ;

替换类“MappingJackson2HttpMessageConverter”

【讨论】:

以上是关于Spring Boot:在 JSONP 回调函数名称之前删除 /**/的主要内容,如果未能解决你的问题,请参考以下文章

JSONP / DOM / BOM 部分总结

jsonp

在 AngularJS 中设置 JSONP 回调函数

Spring Boot CORS支持

jquery jsonp请求错误处理

jsonp回调函数没有被调用