2015-11-09 2 views
1

Я пытаюсь ответить JSONP с помощью @ControllerAdvice. Но перед вызовом функции обратного вызова появляется ненужный комментарий.Spring Boot: Удалить/**/до имени функции обратного вызова 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}); 

Как я могу удалить/** /, прежде чем обратный вызов?
Спасибо.

ответ

0

@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»

1

я наткнулся на точно такую ​​же проблему, как вы, и, таким образом, нашла свой пост. Однако, основываясь на Spring загрузки исходный код:

@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("/**/");, я действительно не думаю, что автор добавил это заявление по ошибке, он должен быть добавлен нарочно и он не хочет, чтобы его вообще удаляли. Поэтому любопытство побудило меня расследовать этот вопрос в течение нескольких часов. Причина добавления оператора generator.writeRaw("/**/");, то есть/**/перед именем функции обратного вызова jsonp, является безопасностью.

Из ссылки https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/, донесло «Для того, чтобы быть также защищен от content sniffing attacks(click to see the meaning), перед именем отраженного обратного вызова с/** /. Это именно то, что Google, Facebook и GitHub в настоящее время делают.»

Даже Google, Facebook и GitHub в настоящее время делают это, есть ли смысл удалить /**/? По моему скромному мнению, мы должны обязательно держать его там. Я попытался использовать обратный вызов jsonp с добавленным /**/ в html-клиенте, и он все еще может работать исправно. Более того, реализация обратного вызова jsonp должна принимать во внимание другие рекомендации по смягчению и исправлению от https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/. В качестве типичного примера используется реализация API Yahoo 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 . Можно прочитать информацию заголовка с помощью некоторого инструмента чтения заголовков, чтобы увидеть, как он реализован с целью избежать захвата json.

0

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

как выше по причине безопасности кода, на самом деле, есть еще один способ сделать это:

generator.writeRaw("\r\n")

избежать XSS нападение.

Смежные вопросы