JSON in Java and Jackson Part ③ Embed JSON in HTML and use it from JavaScript

Introduction

When using JSON, I think that there are many cases where data is sent and received from JavaScript via Ajax. However, there are cases where you want to receive JSON data and use it in JavaScript when HTML is received from the server. In this case, JSON data will be embedded in the HTML returned from the server and read as a JavaScript object. When using PHP, there was an example described in Embedding JSON data in HTML and using it from JavaScript, but our Java (Servlet / Since there was no case by JSP), the result of struggling is left here.

environment

Let's do it without thinking ⇒ Failure

Server side

The server side is as follows. As for "<" and ">", as in previous, they may be interpreted as HTML tags, so Unicode escape sequence conversion is left as it is. There is. The difference from the last time is that the JSON string is saved as a parameter of HttpRequest and it is processed by JSP. Details will be explained on the client side. Also, as mean data, I put \ at the end of the data like " Programmer "⇒" Programmer \ ".

ServletTest2.java


package servletTest;

import java.io.IOException;
import java.util.List;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletContext;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@WebServlet("/helloworld2")
public class ServletTest2 extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

    	//Set a value in a Java object
    	JsonBean jsonBean = new JsonBean();
    	jsonBean.setId(1);
    	jsonBean.setName("kimisyo");
    	List<String> datas = new ArrayList<>();
    	datas.add("Programmer\\");
    	datas.add("Data Scientist<script>alert('hello!')</script>");
    	jsonBean.setDatas(datas);

    	ObjectMapper mapper = new ObjectMapper();
    	mapper.getFactory().setCharacterEscapes(new CustomCharacterEscapes());

    	//Convert from Java object to JSON
    	String testJson = mapper.writeValueAsString(jsonBean);

    	//Set JSON string to request
    	request.setAttribute("jsonStr", testJson);
    	ServletContext sc = getServletContext();
    	sc.getRequestDispatcher("/clientTest2.jsp").forward(request, response);

    }
}

Client side

The client side describes the process in jsp. The JSON string set as a parameter of HttpRequest is temporarily saved in a Java variable, and it is set in the JSON Parse argument in JavaScript. If this works, JSON can be handled through an object called data.

clientTest2.jsp


<%@ page contentType="text/html; charset=UTF-8"%>
<%
	String jsonStr = (String)request.getAttribute("jsonStr");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script>
	var data = JSON.parse('<%=jsonStr%>');
     alert(data.datas);
</script>
</head>
<body>
</body>
</html>

Failure situation

When I run the Servlet above, the `SCRIPT1014: characters are incorrect in JSON.parse. I get a JavaScript error `` (check with the IE console). The HTML that is finally output to the browser is as follows. The \ in the JSON has been properly escaped to \\ by Jackson, and the "<" and ">" have been converted to Unicode escape sequences. At first glance it looks fine.

Now let's think about what went wrong.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script>
	var data = JSON.parse('{"id":1,"name":"kimisyo","datas":["Programmer\\","Data Scientist\u003Cscript\u003Ealert(\u0027hello!\u0027)\u003C\u002Fscript\u003E"]}');
	alert(data.datas);
</script>
</head>
<body>
	<div id="test"></div>
</body>
</html>

Cause of failure

The cause of the failure is the omission of escape of the JavaScript string. In JavaScript, \ is used as an escape character. Therefore, ```" Programmer \ "" is recognized as " Programmer \ " `` as a JavaScript character string. This is passed to JSON.Parse, but even in JSON, the character itself of "" must be escaped like "\", so it is treated as invalid JSON data.

Countermeasures

As a countermeasure, you can escape it for JavaScript and then give it to the JSON.parse argument. The modified source is described below. Here, as the escape of the JavaScript character string, the process for escaping "" and "'" is included.

clientTest2.jsp


<%@ page contentType="text/html; charset=UTF-8"%>
<%
	String jsonStr = (String)request.getAttribute("jsonStr");
	jsonStr = jsonStr.replace("\\", "\\\\");
	jsonStr = jsonStr.replace("'", "\\'");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script>
	var data = JSON.parse('<%=jsonStr%>');
     alert(data.datas);
</script>
</head>
<body>
</body>
</html>

This correctly loaded the JSON string into the JSON object. As an aside, if you escape "" for JavaScript, the "" used in Unicode escape sequence converted characters (eg "\ u0027") is also escaped and converted to "\\ u0027". You might wonder if it's going to go crazy. Actually, "\\ u0027" is interpreted by JavaScript as "\ u0027" and it is given to the argument of JSON.parse, so it is interpreted as a Unicode escape sequence on the JSON side. In other words, the same form as in the case of the previous XSS countermeasure is loaded in JSON, and rather this is the intended operation. Before escaping for JavaScript, it was actually interpreted as a Unicode escape sequence on the HTML side. Well, it's deep.

in conclusion

After all, it was a sober punch line that was a JavaScript escape. When I started this series, I wanted to write this article, so I'd like to conclude it for the time being.

By the way, in the example on the server side of this article, the reason why I explain using Servlet without using the WEB framework is that I can only use Servlet separately, I do not want to use Servlet, and elements that are not related to the theme of this article I wanted to exclude and focus only on the essential parts.

reference

-Embed JSON data in HTML and use it from JavaScript -Escape JavaScript strings

Recommended Posts

JSON in Java and Jackson Part ③ Embed JSON in HTML and use it from JavaScript
JSON in Java and Jackson Part 1 Return JSON from the server
JSON with Java and Jackson Part 2 XSS measures
Convert JSON and YAML in Java (using Jackson and SnakeYAML)
Convert Java enum enums and JSON to and from Jackson
[Java] Convert JSON to Java and Java to JSON-How to use GSON and Jackson-
How to use JSON data in WebSocket communication (Java, JavaScript)
Implement Java Interface in JRuby class and call it from Java
Use OpenCV_Contrib (ArUco) in Java! (Part 2-Programming)
Call Java method from JavaScript executed in Java
Using JavaScript from Java in Rhino 2021 version
Use "Rhino" which runs JavaScript in Java
[Java] Get Json from URL and handle it with standard API (javax.script)
Sample code to serialize and deserialize Java Enum enums and JSON in Jackson
Gradle automatically generates version number from git and uses it in Java
[Java] Output the result of ffprobe -show_streams in JSON and map it to an object with Jackson
Use OpenCV_Contrib (ArUco) in Java! (Part 1-Build) (OpenCV-3.4.4)
Java: Download the file and save it in the location selected in the dialog [Use HttpClient]
Differences in writing Java, C # and Javascript classes
Capture and save from selenium installation in Java
Java and JavaScript
Generate OffsetDateTime from Clock and LocalDateTime in Java
[Android development] Get an image from the server in Java and set it in ImageView! !!
How to embed JavaScript variables in HTML with Thymeleaf
Write a class in Kotlin and call it in Java
Reverse Enum constants from strings and values in Java
Use of Abstract Class and Interface properly in Java
Read JSON in Java
Use java.time in Jackson
Use OpenCV in Java
POST JSON in Java
Create JSON in Java
Use PreparedStatement in Java
What I learned in Java (Part 4) Conditional branching and repetition
How to call and use API in Java (Spring Boot)
[Kotlin] Get Java Constructor / Method from KFunction and call it
Correct the character code in Java and read from the URL
Reasons to use Servlet and JSP separately in Java development
Get attributes and values from an XML file in Java
[Java] JSON communication with jackson
Try calling JavaScript in Java
Java and Iterator Part 1 External Iterator
Use ruby variables in javascript.
Apache Hadoop and Java 9 (Part 1)
POST Json in Java ~ HttpURLConnection ~
Json serialization / deserialization in Java 1.4
Use Redis Stream in Java
JavaScript as seen from Java
Install the memcached plugin on MySQL and access it from Java
What I have learned in Java (Part 1) Java development flow and overview
[Java8] Proper use of Comparable and Comparator in terms of employee sorting
[Android] Convert Map to JSON using GSON in Kotlin and Java
Steps to install Maven on Mac and use it in Eclipse