Lorsque vous utilisez JSON, je pense qu'il existe de nombreux cas où des données sont envoyées et reçues de JavaScript via Ajax. Cependant, dans certains cas, vous souhaitez recevoir des données JSON et les utiliser dans JavaScript lorsque du code HTML est reçu du serveur. Dans ce cas, les données JSON sont intégrées dans le HTML renvoyé par le serveur et lues comme un objet JavaScript. Lors de l'utilisation de PHP, il y avait un exemple décrit dans Incorporer des données JSON dans HTML et l'utiliser à partir de JavaScript, mais notre Java (Servlet / Puisqu'il n'y avait pas de cas par JSP), le résultat de la lutte est laissé ici.
Le côté serveur est le suivant. Quant à "<" et ">", comme pour previous, ils peuvent être interprétés comme des balises HTML, donc la conversion de la séquence d'échappement Unicode est laissée telle quelle. Il y a. La différence par rapport à l'heure précédente est que la chaîne de caractères JSON est enregistrée en tant que paramètre de HttpRequest et est traitée par JSP. Les détails seront expliqués côté client.
Aussi, comme données moyennes, je mets \ à la fin des données comme
"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 {
//Définir la valeur dans l'objet Java
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());
//Convertir d'un objet Java en JSON
String testJson = mapper.writeValueAsString(jsonBean);
//Définir la chaîne JSON à demander
request.setAttribute("jsonStr", testJson);
ServletContext sc = getServletContext();
sc.getRequestDispatcher("/clientTest2.jsp").forward(request, response);
}
}
Le côté client décrit le processus dans jsp. La chaîne de caractères JSON définie comme paramètre de HttpRequest est temporairement enregistrée dans une variable Java et définie dans l'argument JSON Parse en JavaScript. Si cela fonctionne, JSON peut être géré via un objet appelé 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>
Lorsque j'exécute le servlet ci-dessus, le caractère SCRIPT1014: est incorrect dans JSON.parse. J'obtiens une erreur JavaScript
'' (vérifier sur la console IE). Le code HTML qui est finalement sorti dans le navigateur est le suivant.
Le \ dans le JSON a été correctement échappé à \\ par Jackson, et les "<" et ">" ont été convertis en une séquence d'échappement Unicode. À première vue, ça a l'air bien.
Pensons maintenant à ce qui n'a pas fonctionné.
<!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>
La cause de l'échec est l'omission de l'échappement de la chaîne de caractères JavaScript. En JavaScript, \ est utilisé comme caractère d'échappement. Par conséquent,
Programmer \ "" est reconnu comme
'' Programmer \ "` `` comme une chaîne de caractères JavaScript. Ceci est passé à JSON.Parse, mais même dans JSON, le caractère lui-même de "" doit être échappé comme "\", il est donc traité comme des données JSON non valides.
En guise de contre-mesure, échappez au traitement de JavaScript, puis donnez-le à l'argument de JSON.parse. La source modifiée est décrite ci-dessous. Ici, comme échappement de la chaîne de caractères JavaScript, le processus pour échapper "" et "'" est inclus.
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>
Cela a correctement chargé la chaîne JSON dans l'objet JSON. En passant, si vous échappez "" pour JavaScript, le "" utilisé dans les caractères convertis de la séquence d'échappement Unicode (par exemple "\ u0027") sera également échappé et converti en "\\ u0027". Vous pourriez vous demander si ça va devenir fou. En fait, "\\ u0027" est interprété par JavaScript comme "\ u0027" et donné à l'argument de JSON.parse, il est donc interprété comme une séquence d'échappement Unicode du côté JSON. En d'autres termes, la même forme que la contre-mesure XSS précédente est chargée dans JSON, et c'est plutôt l'opération prévue. Avant de s'échapper pour JavaScript, il était en fait interprété comme une séquence d'échappement Unicode côté HTML. Eh bien, c'est profond.
Après tout, c'était une ligne de frappe sobre qui était une évasion JavaScript. Quand j'ai commencé cette série, je voulais écrire cet article, j'aimerais donc le conclure pour le moment.
Au fait, dans l'exemple côté serveur de cet article, la raison pour laquelle j'explique l'utilisation de Servlet sans utiliser le framework WEB est que je ne peux utiliser Servlet que séparément, je ne veux pas utiliser Servlet, éléments non liés au thème de cet article Je voulais exclure et me concentrer uniquement sur les parties essentielles.