diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/GsonHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/GsonHttpMessageConverter.java index be5b4ea6d8..f6b37361fa 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/GsonHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/GsonHttpMessageConverter.java @@ -101,17 +101,16 @@ public class GsonHttpMessageConverter extends AbstractHttpMessageConverterPrefixing the JSON string in this manner is used to help prevent JSON * Hijacking. The prefix renders the string syntactically invalid as a script - * so that it cannot be hijacked. This prefix does not affect the evaluation - * of JSON, but if JSON validation is performed on the string, the prefix - * would need to be ignored. + * so that it cannot be hijacked. + * This prefix should be stripped before parsing the string as JSON. * @see #setJsonPrefix */ public void setPrefixJson(boolean prefixJson) { - this.jsonPrefix = (prefixJson ? "{} && " : null); + this.jsonPrefix = (prefixJson ? ")]}', " : null); } diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java index 8da060c04a..6f7594aaa6 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.java @@ -76,15 +76,14 @@ public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMes } /** - * Indicate whether the JSON output by this view should be prefixed with "{} &&". Default is false. + * Indicate whether the JSON output by this view should be prefixed with ")]}', ". Default is false. *

Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. * The prefix renders the string syntactically invalid as a script so that it cannot be hijacked. - * This prefix does not affect the evaluation of JSON, but if JSON validation is performed on the - * string, the prefix would need to be ignored. + * This prefix should be stripped before parsing the string as JSON. * @see #setJsonPrefix */ public void setPrefixJson(boolean prefixJson) { - this.jsonPrefix = (prefixJson ? "{} && " : null); + this.jsonPrefix = (prefixJson ? ")]}', " : null); } diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java index fedf6232f5..fce8cb3ab7 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java @@ -210,15 +210,15 @@ public class GsonHttpMessageConverterTests { MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); this.converter.setPrefixJson(true); this.converter.writeInternal("foo", outputMessage); - assertEquals("{} && \"foo\"", outputMessage.getBodyAsString(UTF8)); + assertEquals(")]}', \"foo\"", outputMessage.getBodyAsString(UTF8)); } @Test public void prefixJsonCustom() throws Exception { MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); - this.converter.setJsonPrefix(")]}',"); + this.converter.setJsonPrefix(")))"); this.converter.writeInternal("foo", outputMessage); - assertEquals(")]}',\"foo\"", outputMessage.getBodyAsString(UTF8)); + assertEquals(")))\"foo\"", outputMessage.getBodyAsString(UTF8)); } diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java index cfe9bca095..aaa9fa0f78 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java @@ -233,16 +233,16 @@ public class MappingJackson2HttpMessageConverterTests { this.converter.setPrefixJson(true); this.converter.writeInternal("foo", outputMessage); - assertEquals("{} && \"foo\"", outputMessage.getBodyAsString(Charset.forName("UTF-8"))); + assertEquals(")]}', \"foo\"", outputMessage.getBodyAsString(Charset.forName("UTF-8"))); } @Test public void prefixJsonCustom() throws Exception { MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); - this.converter.setJsonPrefix(")]}',"); + this.converter.setJsonPrefix(")))"); this.converter.writeInternal("foo", outputMessage); - assertEquals(")]}',\"foo\"", outputMessage.getBodyAsString(Charset.forName("UTF-8"))); + assertEquals(")))\"foo\"", outputMessage.getBodyAsString(Charset.forName("UTF-8"))); } @Test diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java index 1eefee90b9..5799207387 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java @@ -99,16 +99,15 @@ public class MappingJackson2JsonView extends AbstractJackson2View { } /** - * Indicates whether the JSON output by this view should be prefixed with "{} && ". + * Indicates whether the JSON output by this view should be prefixed with ")]}', ". * Default is {@code false}. *

Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. * The prefix renders the string syntactically invalid as a script so that it cannot be hijacked. - * This prefix does not affect the evaluation of JSON, but if JSON validation is performed - * on the string, the prefix would need to be ignored. + * This prefix should be stripped before parsing the string as JSON. * @see #setJsonPrefix */ public void setPrefixJson(boolean prefixJson) { - this.jsonPrefix = (prefixJson ? "{} && " : null); + this.jsonPrefix = (prefixJson ? ")]}', " : null); } /** diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/json/MappingJackson2JsonViewTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/json/MappingJackson2JsonViewTests.java index f93331764a..3b61f75e9f 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/json/MappingJackson2JsonViewTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/json/MappingJackson2JsonViewTests.java @@ -48,6 +48,7 @@ import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.ScriptableObject; +import org.springframework.beans.DirectFieldAccessor; import org.springframework.http.MediaType; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; @@ -180,14 +181,14 @@ public class MappingJackson2JsonViewTests { public void renderSimpleBeanPrefixed() throws Exception { view.setPrefixJson(true); renderSimpleBean(); - assertTrue(response.getContentAsString().startsWith("{} && ")); + assertTrue(response.getContentAsString().startsWith(")]}', ")); } @Test public void renderSimpleBeanNotPrefixed() throws Exception { view.setPrefixJson(false); renderSimpleBean(); - assertFalse(response.getContentAsString().startsWith("{} && ")); + assertFalse(response.getContentAsString().startsWith(")]}', ")); } @Test @@ -363,8 +364,14 @@ public class MappingJackson2JsonViewTests { } private void validateResult() throws Exception { + String json = response.getContentAsString(); + DirectFieldAccessor viewAccessor = new DirectFieldAccessor(view); + String jsonPrefix = (String)viewAccessor.getPropertyValue("jsonPrefix"); + if (jsonPrefix != null) { + json = json.substring(5); + } Object jsResult = - jsContext.evaluateString(jsScope, "(" + response.getContentAsString() + ")", "JSON Stream", 1, null); + jsContext.evaluateString(jsScope, "(" + json + ")", "JSON Stream", 1, null); assertNotNull("Json Result did not eval as valid JavaScript", jsResult); assertEquals("application/json", response.getContentType()); }