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.
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);
}
}
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>
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>
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.
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.
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.
-Embed JSON data in HTML and use it from JavaScript -Escape JavaScript strings
Recommended Posts