JSON en Java et Jackson Part ③ Incorporer JSON dans HTML et l'utiliser à partir de JavaScript

introduction

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.

environnement

Faisons-le sans réfléchir ⇒ Échec

Du côté serveur

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);

    }
}

Côté client

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>

Situation d'échec

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>

Cause de l'échec

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.

Contre-mesures

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.

en conclusion

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.

référence

Recommended Posts

JSON en Java et Jackson Part ③ Incorporer JSON dans HTML et l'utiliser à partir de JavaScript
JSON en Java et Jackson Partie 1 Renvoyer JSON à partir du serveur
JSON avec Java et Jackson Part 2 XSS mesures
Convertir JSON et YAML en Java (en utilisant Jackson et SnakeYAML)
Convertir l'énumération Java et JSON vers et depuis Jackson
[Java] Convertir JSON en Java et Java en JSON-Comment utiliser GSON et Jackson-
Comment utiliser les données JSON dans la communication WebSocket (Java, JavaScript)
Implémentez l'interface Java dans la classe JRuby et appelez-la depuis Java
Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 2-Programmation)
Appel de méthodes Java à partir de JavaScript exécutées en Java
Utilisez "Rhino" qui exécute JavaScript en Java
[Java] Obtenir et gérer Json à partir d'une URL avec une API standard (javax.script)
Exemple de code pour la sérialisation et la désérialisation des énumérations Java Enum et JSON dans Jackson
Gradle génère automatiquement le numéro de version de git et l'utilise en Java
[Java] Affiche le résultat de ffprobe -show_streams dans JSON et mappe-le à un objet dans Jackson
Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 1-Construire) (OpenCV-3.4.4)
Java: Téléchargez le fichier et enregistrez-le à l'emplacement sélectionné dans la boîte de dialogue [Utiliser HttpClient]
Différences dans l'écriture des classes Java, C # et Javascript
Capture et sauvegarde de l'installation de sélénium en Java
Java et JavaScript
Générer OffsetDateTime à partir de Clock et LocalDateTime en Java
[Développement Android] Obtenez des images du serveur avec Java et définissez-les dans ImageView! !!
Comment intégrer des variables JavaScript dans HTML avec Thymeleaf
Ecrire une classe en Kotlin et l'appeler en Java
Soustraire les constantes Enum des chaînes et des valeurs en Java
Utilisation correcte de la classe abstraite et de l'interface en Java
Lire JSON en Java
Utilisez java.time avec Jackson
Utiliser OpenCV avec Java
POST JSON en Java
Créer JSON en Java
Utiliser PreparedStatement en Java
Ce que j'ai appris en Java (partie 4) Branchement conditionnel et répétition
Comment appeler et utiliser l'API en Java (Spring Boot)
[Kotlin] Obtenez le constructeur / la méthode Java de KFunction et appelez-le
Corrigez le code de caractère en Java et lisez à partir de l'URL
Raisons d'utiliser séparément Servlet et JSP dans le développement Java
Obtenir des attributs et des valeurs à partir d'un fichier XML en Java
[Java] Communication JSON avec jackson
Essayez d'appeler JavaScript en Java
Java et Iterator Part 1 External Iterator Edition
Utilisez des variables ruby en javascript.
Apache Hadoop et Java 9 (partie 1)
POST Json en Java ~ HttpURLConnection ~
Sérialisation / désérialisation Json dans Java 1.4
JavaScript vu de Java
Installez le plugin memcached sur MySQL et accédez à partir de Java
Ce que j'ai appris en Java (partie 1) Flux de développement Java et présentation
[Java8] Utilisation appropriée de Compareable et Comparator du point de vue du tri des employés
[Android] Convertissez Map en JSON à l'aide de GSON avec Kotlin et Java
Étapes pour installer Maven sur Mac et l'utiliser avec Eclipse