[JAVA] So stellen Sie sicher, dass CsrfRequestDataValueProcessor und der ursprüngliche RequestDataValueProcessor beim Spring Boot nebeneinander existieren

Wenn Spring Security beim Spring Boot verwendet wird, wird der von Spring Security bereitgestellte "CsrfRequestDataValueProcessor" (eine Klasse zum Ausgeben des CSRF-Token-Werts an das ausgeblendete Formular) angewendet, und der projektspezifische "RequestDataValueProcessor" kann nicht angewendet werden. Dies ist ... Es scheint, dass das Problem von Spring Boot (gh-4676) diskutiert, wie man damit umgeht, aber es ist immer noch eine Schlussfolgerung. Scheint nicht zu erscheinen.

Problemumgehung

In Ausgabe ...

Wird als Problemumgehung eingeführt.

Erstellen Sie Ihre eigene AutoConfigure-Klasse und versuchen Sie, sie zu lösen

Dieses Mal werde ich versuchen, meine eigene AutoConfigure-Klasse zu erstellen und @ AutoConfigureAfter zu verwenden, um die Bean-Definition in SecurityAutoConfiguration.class zu überschreiben. Der projektspezifische RequestDataValueProcessor gibt allgemeine Parameter aus (_s = Millisekunden für Systemdatum und -zeit), um ein Zwischenspeichern der URL in den Elementen form und a zu vermeiden.

Erstellen Sie Ihre eigene AutoConfigure-Klasse

Die diesmal erstellte Klasse berücksichtigt die Vielseitigkeit überhaupt nicht und verwendet eine Implementierungsmethode, die die projektspezifische Implementierung von "RequestDataValueProcessor" auf die Anwendung anwendet, während die von "CsrfRequestDataValueProcessor" bereitgestellten Funktionen beibehalten werden.

Note:

Wenn Sie die Vielseitigkeit berücksichtigen ... Es ist besser, eine zusammengesetzte Klasse von "RequestDataValueProcessor" zu erstellen, die die Verarbeitung an mehrere "RequestDataValueProcessor" delegiert.

package com.example;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
import org.springframework.web.util.UriComponentsBuilder;

@Configuration
@AutoConfigureAfter(SecurityAutoConfiguration.class) //★★★ Hier Punkte[1]
public class MyRequestDataValueProcessorAutoConfiguration {
	@Bean
	RequestDataValueProcessor requestDataValueProcessor() { //★★★ Hier Punkte[2]
		CsrfRequestDataValueProcessor csrfRequestDataValueProcessor = new CsrfRequestDataValueProcessor();
		return new RequestDataValueProcessor() {
			@Override
			public String processAction(HttpServletRequest request, String action, String httpMethod) {
				return addCachePreventQueryParameter(csrfRequestDataValueProcessor.processAction(request, action, httpMethod));
			}

			@Override
			public String processFormFieldValue(HttpServletRequest request, String name, String value, String type) {
				return csrfRequestDataValueProcessor.processFormFieldValue(request, name, value, type);
			}

			@Override
			public Map<String, String> getExtraHiddenFields(HttpServletRequest request) {
				return csrfRequestDataValueProcessor.getExtraHiddenFields(request);
			}

			@Override
			public String processUrl(HttpServletRequest request, String url) {
				return addCachePreventQueryParameter(csrfRequestDataValueProcessor.processUrl(request, url));
			}

			private String addCachePreventQueryParameter(String url) {
				return UriComponentsBuilder.fromUriString(url).queryParam("_s", System.currentTimeMillis()).build().encode()
						.toUriString();
			}
		};
	}

}

[1] Indem Sie zulassen, dass Ihre eigene AutoConfigure-Klasse nach "SecurityAutoConfiguration" aufgerufen wird, können Sie die von Spring Boot (Spring Security) bereitgestellte Bean-Definition mit Ihrer eigenen AutoConfigure-Klasse überschreiben. [2] Um die Bean-Definition zu überschreiben, muss der Bean-Name "requestDataValueProcessor" sein.


Grundsätzlich delegiert es den Prozess an "CsrfRequestDataValueProcessor" und implementiert ihn, um den Rückgabewerten von "processAction" und "processUrl" einen Cache-Vermeidungsparameter hinzuzufügen.

Um die erstellte Konfigurationsklasse als AutoConfigure-Klasse zu erkennen, erstellen Sie "src / main / resources / META-INF / spring.factories" und verwenden Sie den Eigenschaftsschlüsselwert "org.springframework.boot.autoconfigure.EnableAutoConfiguration". Sie müssen die Klasse angeben, in der Sie erstellt haben.

src/main/resources/META-INF/spring.factories


# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyRequestDataValueProcessorAutoConfiguration

Eine Ansicht erstellen (Thymeleaf)

Lassen Sie uns eine einfache Ansicht für die Betriebsüberprüfung erstellen.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Demo</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" type="text/css"/>
</head>
<body>

<div class="container">

    <h1>Demo</h1>


    <div id="demoForm">
        <form action="index.html" method="post" class="form-horizontal"
              th:action="@{/demo}" th:object="${demoForm}"> <!--★★★ Hier Punkte[3] -->
            <div class="form-group">
                <label for="title" class="col-sm-1 control-label">Title</label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="title" th:field="*{title}"/>
                    <span class="text-error" th:errors="*{title}">error message</span>
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-offset-1 col-sm-10">
                    <button type="submit" class="btn btn-default">Create</button>
                </div>
            </div>
        </form>
    </div>

    <a href="index.html" th:href="@{/demo}">Reload</a> <!--★★★ Hier Punkte[4] -->

</div>
</body>
</html>

[3] Die in th: action angegebene URL wird von der Methode RequestDataValueProcessor # processAction verarbeitet. [4] Die in th: href angegebene URL wird von der Methode RequestDataValueProcessor # processUrl verarbeitet.


Wenn der obige HTML-Code beim Spring Boot ausgeführt wird, wird der folgende HTML-Code generiert. Die URL des "action" -Attributs des "form" -Elements und des "href" -Attributs des "a" -Elements enthält einen Cache-Vermeidungsparameter und das "hidden" zum Verknüpfen des CSRF-Token-Werts im "form" -Element. Sie können sehen, dass das Element ausgegeben wird.

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Demo</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" type="text/css" />
</head>
<body>

<div class="container">

    <h1>Demo</h1>


    <div id="demoForm">
        <form action="/demo?_s=1488222896002" method="post" class="form-horizontal"> <!--★★★ Der Cache-Vermeidungsparameter ist angegeben-->
            <div class="form-group">
                <label for="title" class="col-sm-1 control-label">Title</label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="title" name="title" value="" />
                    
                </div>
            </div>
            <div class="form-group">
                <div class="col-sm-offset-1 col-sm-10">
                    <button type="submit" class="btn btn-default">Create</button>
                </div>
            </div>
        <input type="hidden" name="_csrf" value="b952a1bf-222a-4a99-b889-6878935a5784" /></form> <!--★★★ Die versteckte Verknüpfung von CSRF-Token-Werten ist angegeben.-->
    </div>

    <a href="/demo?_s=1488222896002">Reload</a> <!--★★★ Der Cache-Vermeidungsparameter ist angegeben-->

</div>
</body>
</html>

Controller erstellen

RequestDataValueProcessor # processUrl ist mit der Umleitungsfunktion von Spring MVC verknüpft. Überprüfen wir also auch dort den Vorgang.

package com.example;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/demo")
@Controller
public class DemoController {

	@ModelAttribute
	DemoForm setUpForm() {
		return new DemoForm();
	}

	@GetMapping
	String index() {
		return "index";
	}

	@PostMapping
	String submit(DemoForm form) {
		return "redirect:/demo"; //★★★ Hier Punkte[5]
	}

	static class DemoForm {
		private String title;

		public String getTitle() {
			return title;
		}

		public void setTitle(String title) {
			this.title = title;
		}
	}

}

[5] Die bei Verwendung der Spring MVC-Umleitungsfunktion angegebene URL wird von der Methode "RequestDataValueProcessor # processUrl" verarbeitet.


Wenn Sie die Umleitungs-URL mit dem Entwicklertool des Browsers überprüfen, können Sie feststellen, dass der Parameter zur Vermeidung von Cache ordnungsgemäß zugewiesen ist.

HTTP/1.1 302
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://localhost:8080/demo?_s=1488223437196 #★★★ Der Cache-Vermeidungsparameter ist angegeben
Content-Language: en-US
Content-Length: 0
Date: Mon, 27 Feb 2017 19:23:57 GMT

Zusammenfassung

Durch das Erstellen meiner eigenen AutoConfigure-Klasse konnte ich "CsrfRequestDataValueProcessor" und meinen eigenen "RequestDataValueProcessor" koexistieren lassen. Es wurde auch bestätigt, dass mithilfe von "RequestDataValueProcessor" allgemeine Parameter zu den unter Spring MVC behandelten URLs hinzugefügt werden können. Allerdings ... Wenn URLs außerhalb der Spring MVC-Verwaltung verarbeitet werden (z. B. wenn die Methode von "HttpServletResponse" direkt verarbeitet wird), unterliegt sie nicht der Zuständigkeit von "RequestDataValueProcessor", sodass keine allgemeinen Parameter zugewiesen werden können. Wenn Sie URLs, die nicht von Spring MVC verwaltet werden, allgemeine Parameter hinzufügen möchten, müssen Sie "HttpServletResponseWrapper" erstellen, um allgemeine Parameter anzugeben, diese in die von Servlet Filter erstellte Klasse einschließen und die nachfolgende Verarbeitung aufrufen. Ich werde.

Recommended Posts

So stellen Sie sicher, dass CsrfRequestDataValueProcessor und der ursprüngliche RequestDataValueProcessor beim Spring Boot nebeneinander existieren
So verkleinern Sie das Spring Boot Docker-Image
Aufrufen und Verwenden der API in Java (Spring Boot)
So stellen Sie Spring Boot + PostgreSQL ein
Verwendung von ModelMapper (Spring Boot)
So erstellen Sie mit SPRING INITIALIZR einen Hinadan für ein Spring Boot-Projekt
So teilen Sie eine Spring Boot-Nachrichtendatei
Fügen Sie Frühlingsstiefel und Gradle zur Sonnenfinsternis hinzu
Anzeigen der in Spring Boot eingegebenen Zeichen im Browser und Referenzlinks [Einführung in Spring Boot / Für Anfänger]
Verwendung von MyBatis2 (iBatis) mit Spring Boot 1.4 (Spring 4)
Verwendung des eingebauten h2db mit Federstiefel
Verwendung von Spring Boot-Sitzungsattributen (@SessionAttributes)
So fügen Sie in Spring Boot einen Klassenpfad hinzu
So binden Sie mit einer Eigenschaftendatei in Spring Boot
[Spring Boot] So verweisen Sie auf die Eigenschaftendatei
Spring Boot - So stellen Sie das Sitzungszeitlimit ein
Pläne zur Unterstützung von JDK 11 für Eclipse und Spring Boot
So stellen Sie Spring Boot Dependency Injection (DI) ein
So schreiben Sie einen Komponententest für Spring Boot 2
So implementieren Sie den Authentifizierungsprozess durch Angabe von Benutzername und Kennwort in Spring Boot
So erstellen Sie ein Spring Boot-Projekt in IntelliJ
[Spring Boot] So erstellen Sie ein Projekt (für Anfänger)
So funktioniert JavaScript auf einer bestimmten Seite
Verwendung von CommandLineRunner im Spring Batch von Spring Boot
Stellen Sie das Spring Boot-Projekt in XAMPP für Tomcat bereit
Booten nach Umgebung mit Spring Boot of Maven
Versuch, SSR Vue.js mit Spring Boot und GraalJS zu verwenden
(Ruby on Rails6) So erstellen Sie ein Modell und eine Tabelle
So verwenden Sie OpenCV 4 unter Android und zeigen die Kamera live an
So ändern Sie den Einstellungswert von application.properties beim Booten im Frühjahrsstart
Bis INSERT und SELECT für Postgres mit Spring Boot und Thymianblatt
Ich habe versucht, Java Optional und Guard-Klausel koexistieren zu lassen
Stellen Sie mit spring boot + spring jpa eine Verbindung zur Datenbank her und führen Sie die CRUD-Operation durch
So führen Sie React und Rails auf demselben Server aus
8 Dinge, die mit Spring Boot und JPA in die DB eingefügt werden müssen
So steuern Sie Transaktionen in Spring Boot ohne Verwendung von @Transactional
Versuchen Sie Spring Boot von 0 bis 100.
Spring Boot unter Microsoft Azure
Java - So erstellen Sie JTable
Wie man mit Heroku einsetzt
Einführung in Spring Boot ~ ~ DI ~
Einführung in Spring Boot Teil 1
Versuchen Sie Spring Boot auf dem Mac
[Schienen] Wie man Samen macht
So installieren und verwenden Sie Composer auf einer ECS-Instanz unter Ubuntu 16.04
Mindestkonfiguration zum Ausführen der Spring Boot-Anwendung in Azure Web Apps
So erstellen Sie mit Spring Boot einen eigenen Controller, der / error entspricht
So legen Sie ein Profil mit annotationsbasierter Konfiguration im Spring-Framework fest und verwenden es
So installieren und konfigurieren Sie das Überwachungstool "Graphite" unter Ubuntu
So laden Sie eine Spring-Upload-Datei und zeigen ihren Inhalt an
Wie man Lombok im Frühling benutzt
Verwendung von StringBurrer und Arrays.toString.
So führen Sie einen Komponententest für Spring AOP durch
gRPC auf Spring Boot mit grpc-spring-boot-Starter
Wie man eine Ansicht auf Android "aushöhlt"
Hinweise zur Verwendung von Spring Data JDBC