Ich denke, bei der Verwendung von JSON gibt es viele Fälle, in denen Daten von JavaScript über Ajax gesendet und empfangen werden. Es gibt jedoch Fälle, in denen Sie JSON-Daten empfangen und in JavaScript verwenden möchten, wenn HTML vom Server empfangen wird. In diesem Fall werden JSON-Daten in den vom Server zurückgegebenen HTML-Code eingebettet und als JavaScript-Objekt gelesen. Bei der Verwendung von PHP wurde ein Beispiel unter Einbetten von JSON-Daten in HTML und deren Verwendung aus JavaScript beschrieben, aber unser Java (Servlet / Da es keinen Fall von JSP gab, bleibt das Ergebnis des Kampfes hier.
Die Serverseite ist wie folgt. "<" Und ">" können wie bei vorherige als HTML-Tags interpretiert werden, sodass die Konvertierung der Unicode-Escape-Sequenz unverändert bleibt. Es gibt. Der Unterschied zum vorherigen Zeitpunkt besteht darin, dass die JSON-Zeichenfolge als Parameter von HttpRequest gespeichert und von JSP verarbeitet wird. Details werden auf der Client-Seite erklärt.
Als mittlere Daten setze ich \ am Ende der Daten wie `" 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 {
//Legen Sie einen Wert in einem Java-Objekt fest
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());
//Vom Java-Objekt in JSON konvertieren
String testJson = mapper.writeValueAsString(jsonBean);
//Stellen Sie die JSON-Zeichenfolge auf Anforderung ein
request.setAttribute("jsonStr", testJson);
ServletContext sc = getServletContext();
sc.getRequestDispatcher("/clientTest2.jsp").forward(request, response);
}
}
Die Client-Seite beschreibt den Prozess in jsp. Der als Parameter von HttpRequest festgelegte JSON-Zeichenkettensatz wird vorübergehend in einer Java-Variablen gespeichert und im JavaScript-Argument JSON Parse festgelegt. Wenn dies funktioniert, kann JSON über ein Objekt namens data verarbeitet werden.
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>
Wenn ich das Servlet oben ausführe, ist das Zeichen `SCRIPT1014: in JSON.parse falsch. Ich erhalte einen JavaScript-Fehler
`` (überprüfen Sie auf der IE-Konsole). Der HTML-Code, der schließlich an den Browser ausgegeben wird, lautet wie folgt.
Das \ im JSON wurde von Jackson ordnungsgemäß nach \\ maskiert, und die "<" und ">" wurden in eine Unicode-Escape-Sequenz konvertiert. Auf den ersten Blick sieht es gut aus.
Lassen Sie uns nun darüber nachdenken, was schief gelaufen ist.
<!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>
Die Ursache des Fehlers ist das Weglassen der Escape-Funktion der JavaScript-Zeichenfolge. In JavaScript wird \ als Escapezeichen verwendet. Daher wird `" Programmer \\ ""
als `" Programmer \ "`
als JavaScript-Zeichenfolge erkannt. Dies wird an JSON.Parse übergeben, aber selbst in JSON muss das Zeichen selbst von "" wie "\" maskiert werden, damit es als ungültige JSON-Daten behandelt wird.
Als Gegenmaßnahme entkommen Sie der Verarbeitung für JavaScript und geben Sie sie dann an das Argument von JSON.parse weiter. Die modifizierte Quelle wird unten beschrieben. Hier ist als Escapezeichen der JavaScript-Zeichenfolge der Prozess zum Escapezeichen von "" und "'" enthalten.
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>
Dadurch wurde die JSON-Zeichenfolge korrekt in das JSON-Objekt geladen. Wenn Sie für JavaScript "" maskieren, wird das in der konvertierten Unicode-Escape-Sequenz verwendete "" (z. B. "\ u0027") ebenfalls maskiert und in "\\ u0027" konvertiert. Sie könnten sich fragen, ob es verrückt werden wird. Tatsächlich wird "\\ u0027" von JavaScript als "\ u0027" interpretiert und dem Argument von JSON.parse übergeben, sodass es auf der JSON-Seite als Unicode-Escape-Sequenz interpretiert wird. Mit anderen Worten, in JSON wird dieselbe Form wie im Fall der vorherigen XSS-Gegenmaßnahme geladen, und dies ist vielmehr die beabsichtigte Operation. Vor dem Escape für JavaScript wurde es tatsächlich als Unicode-Escape-Sequenz auf der HTML-Seite interpretiert. Nun, es ist tief.
Immerhin war es eine nüchterne Pointe, die eine JavaScript-Flucht war. Als ich mit dieser Serie anfing, wollte ich diesen Artikel schreiben, deshalb möchte ich ihn vorerst abschließen.
Übrigens, im Beispiel auf der Serverseite dieses Artikels erkläre ich die Verwendung von Servlet ohne Verwendung des WEB-Frameworks, weil ich Servlet nur separat verwenden kann. Ich möchte Servlet nicht verwenden, Elemente, die nicht mit dem Thema dieses Artikels zusammenhängen Ich wollte nur die wesentlichen Teile ausschließen und mich darauf konzentrieren.
Recommended Posts