2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Den Grund finden Sie im folgenden Artikel: Der richtige Weg, domänenübergreifende Probleme durch die Trennung von Front-End und Back-End des sa-token zu lösen
https://mp.weixin.qq.com/s/96WbWL28T5_-xzyCfJ7Stg
https://blog.csdn.net/qq_34905631/article/details/140233780?spm=1001.2014.3001.5501
Obwohl dieser Artikel nach vielen Versuchen die richtige Haltung fand, wurde die Grundursache des Problems nicht gefunden. Nach einigem Nachdenken und Erkunden fragte ich mich, ob diese domänenübergreifende Simulation lokal möglich ist, und begann dann, danach zu suchen Wang, der Front-End-Mitarbeiter des Projekts, simulierte dann tatsächlich lokales Cross-Domain. Im Projekt trennte er das vorherige Sa-Token-Front-End und das Back-End, um die korrekte Situation des Cross-Domain-Problems zu lösen nach dem Kommentar zu SimpleCORSFilter im Artikel.
Die domänenübergreifende Konfiguration des offiziellen mvc spring5.2.15.RELEASE lautet wie folgt:
https://docs.spring.io/spring-framework/docs/5.2.15.RELEASE/spring-framework-reference/web.html#mvc-cors-intro
Befolgen Sie die oben verlinkte offizielle Methode und fügen Sie dann wie folgt eine CustomCorsFilter-Klasse hinzu:
package xxxx.config;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomCorsFilter extends CorsFilter {
public CustomCorsFilter() {
super(corsConfigurationSource());
}
private static CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*"); // 允许访问的域名,例如 http://localhost:8080
configuration.addAllowedHeader("*"); // 允许所有请求头
configuration.addAllowedMethod("*"); // 允许所有请求方法
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Die Konfiguration von CustomCorsFilter wurde in einem Projekt, an dem ich gearbeitet habe, als gültig bestätigt. In einem aktuellen Projekt ist es jedoch sinnlos, diese CustomCorsFilter-Klassenkonfiguration zur Lösung domänenübergreifender Probleme zu verwenden. Im obigen Artikel über die korrekte Lösung domänenübergreifender Probleme durch die Trennung von Sa-Token-Front-End und Back-End war die Überprüfung der CustomCorsFilter-Klasse tatsächlich ungültig. Dieses Problem war wirklich rätselhaft, als ich die CustomCorsFilter-Klasse im Projekt neu konfigurierte (SimpleCORSFilter muss kommentiert werden, da dieser SimpleCORSFilter nach der lokalen Ausführung verwendet werden kann. Nach der lokalen Ausführung des Frontends habe ich einen Haltepunkt in den folgenden Code der CorsFilter-Klasse eingefügt.)
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
//关键就是这里,在这里打上断点
if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return;
}
filterChain.doFilter(request, response);
}
Fügen Sie außerdem einen Haltepunkt für die Methode CorsUtils.isPreFlightRequest ein:
public static boolean isPreFlightRequest(HttpServletRequest request) {
return (HttpMethod.OPTIONS.matches(request.getMethod()) &&
request.getHeader(HttpHeaders.ORIGIN) != null &&
request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
}
Dann sieht der Haltepunkt-Screenshot wie folgt aus:
Die Anmeldeschnittstelle ist eine komplexe domänenübergreifende Anfrage mit http plus Domänenname, und es wird eine Vorerkennungsanfrage (OPTIONS-Anfrage) gesendet.
In dem mit sa-token integrierten Projekt habe ich einen Haltepunkt für die doFilterInternal-Methode von OncePerRequestFilter gesetzt und die folgenden Filter gefunden:
Es ist ersichtlich, dass der oben angepasste CustomCorsFilter zuerst ausgeführt wird und die beiden mit sa-token verbundenen Filter: saPathCheckFilterForServlet und SaServletFilter später ausgeführt werden, sodass andere frühere Vermutungen gut bestätigt wurden. Der Haltepunkt geht an die doFilterInternal-Methode von CorsFilter unten :
//关键就是这里,在这里打上断点
if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return;
}
Das Problem liegt im folgenden Code:
CorsUtils.isPreFlightRequest(request)
Diese Codezeile gab „true“ zurück, daher wurden alle nachfolgenden Filter nicht ausgeführt, sodass der Browser immer noch domänenübergreifende Probleme meldete. Dann habe ich die Codezeile „CorsUtils.isPreFlightRequest“ debuggt. Es wurde festgestellt, dass nach dem Senden einer Voraberkennungsanfrage (OPTIONS-Anfrage) über Domänen hinweg der Ursprung auf unerklärliche Weise festgelegt wurde:
http://localhost:3000
Das war sehr seltsam, also habe ich meinen Front-End-Kollegen Lao Wangbang gebeten, zu überprüfen, wo dieser Wert festgelegt ist, und habe Folgendes gefunden:
Das Frontend legt Origin nicht fest, sondern nur die folgenden Parameter:
//设置axios跨域访问
axios.defaults.withcredentials = true // 设置cross跨域 并设置访问权限 允许跨域携带cookie信息axios.defaults.crossDomain=true //设置axios跨域的配置
Im Bild oben gibt es nur einen Referer-Wert, der mit dem Origin-Wert übereinstimmt. Ist das wirklich nur ein Zufall, also habe ich den folgenden Artikel gelesen:
https://blog.csdn.net/qq_55316925/article/details/128571809
Es hat mir viele Ideen gegeben, also habe ich darüber nachgedacht, und es stellte sich heraus, dass der im Backend konfigurierte CustomCorsFilter effektiv war. Kann ich den CorsFilter-Quellcode ändern, die von mir überprüft wurden? Beim Front-End von Lao Wang sind beide Methoden machbar und beide können das domänenübergreifende Cors-Problem lösen.
Ändern Sie den CorsFilter-Quellcode im Backend
Fügen Sie unter src.main.java unter dem Projekt ein neues Paket org.springframework.web.filter hinzu
Kopieren Sie dann den Quellcode von CorsFilter und fügen Sie ihn unter das oben neu erstellte Paket org.springframework.web.filter ein. Anschließend können Sie den Quellcode von CorsFilter ändern.
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.Assert;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsProcessor;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.DefaultCorsProcessor;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
/**
* {@link javax.servlet.Filter} that handles CORS preflight requests and intercepts
* CORS simple and actual requests thanks to a {@link CorsProcessor} implementation
* ({@link DefaultCorsProcessor} by default) in order to add the relevant CORS
* response headers (like {@code Access-Control-Allow-Origin}) using the provided
* {@link CorsConfigurationSource} (for example an {@link UrlBasedCorsConfigurationSource}
* instance.
*
* <p>This is an alternative to Spring MVC Java config and XML namespace CORS configuration,
* useful for applications depending only on spring-web (not on spring-webmvc) or for
* security constraints requiring CORS checks to be performed at {@link javax.servlet.Filter}
* level.
*
* <p>This filter could be used in conjunction with {@link DelegatingFilterProxy} in order
* to help with its initialization.
*
* @author Sebastien Deleuze
* @since 4.2
* @see <a href="https://www.w3.org/TR/cors/">CORS W3C recommendation</a>
*/
public class CorsFilter extends OncePerRequestFilter {
private final CorsConfigurationSource configSource;
private CorsProcessor processor = new DefaultCorsProcessor();
/**
* Constructor accepting a {@link CorsConfigurationSource} used by the filter
* to find the {@link CorsConfiguration} to use for each incoming request.
* @see UrlBasedCorsConfigurationSource
*/
public CorsFilter(CorsConfigurationSource configSource) {
Assert.notNull(configSource, "CorsConfigurationSource must not be null");
this.configSource = configSource;
}
/**
* Configure a custom {@link CorsProcessor} to use to apply the matched
* {@link CorsConfiguration} for a request.
* <p>By default {@link DefaultCorsProcessor} is used.
*/
public void setCorsProcessor(CorsProcessor processor) {
Assert.notNull(processor, "CorsProcessor must not be null");
this.processor = processor;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
//修改的源码是将CorsUtils.isPreFlightRequest(request)这行代码移除,就是因为复杂请求跨域发了预检测请求,浏览器的referrer-policy引用者策略会携带一个值,后端处理之后会将这个值赋值给请求头的Orgin属性上,移除这行代码之后就可以正常访问到登录接口了,前端也没有报跨域了。
if (!isValid) {
return;
}
filterChain.doFilter(request, response);
}
}
Fügen Sie dem Frontend den folgenden Code hinzu: Deaktivieren oder entfernen Sie die Referrer-Richtlinie „referrer-policy“.
https://blog.csdn.net/qq_49810363/article/details/111036180
Der neue Code lautet wie folgt:
<meta name="referrer" content="never">
Die Referrer-Richtlinie des Browsers dient ebenfalls Sicherheitsgründen. Der von mir verwendete Browser ist der Chrome-Browser.
Nach ständigen Versuchen und Herumtasten trat das Problem der domänenübergreifenden Bereitstellung von cors auf, nachdem das sa-token in das Projekt integriert wurde. Im Allgemeinen erlauben die Spezifikationen des domänenübergreifenden cors-Protokolls diesen Vorgang nicht Die -end-Lösungsbibliothek lässt keine Anforderungsvorgänge zu, die nicht den Spezifikationen des domänenübergreifenden CORS-Protokolls entsprechen. Daher können Sie mit sa-token die Front-End- und Back-End-Lösungen trennen, um die korrekte Position domänenübergreifender Lösungen zu erreichen . Konfigurieren Sie einen SimpleCORSFilter, schreiben Sie bestimmte Parameter und verarbeiten Sie die Vorerkennungsanforderung, um den Statuscode 200 zurückzugeben. Alternativ können Sie eine der beiden Methoden in diesem Artikel verwenden, um das domänenübergreifende Cors-Problem zu lösen Ich debugge es, nachdem ich die domänenübergreifende Anforderung am Haltepunkt reproduziert habe. Lösung: Wenn Sie glauben, dass Sie der Methode in diesem Artikel folgen können, reproduzieren Sie die domänenübergreifende Anforderung lokal und debuggen Sie dann den Haltepunkt, um festzustellen, ob es sich um ein Problem handelt Die CorsUtils.isPreFlightRequest(request)-Zeile von corsFilter ist im Allgemeinen ein großes Problem für Browser. Eine einfache Anfrage an corsFilter schlägt nicht fehl. Da die Referrer-Richtlinie des Browsers einen Wert enthält, wird dieser Wert nach der Back-End-Verarbeitung dem Origin-Attribut des Anforderungsheaders zugewiesen, wodurch die Codezeile CorsUtils.isPreFlightRequest(request) von corsFilter „true“ zurückgibt und dann zurückkehren, wird der doFilter der nachfolgenden Filterreihe nicht ausgeführt und es gibt keinen Zugriff auf die Back-End-Schnittstelle, und die Front-End-Browserseite meldet ehrlich gesagt immer noch domänenübergreifende Probleme , dieses Problem ist wirklich ärgerlich. Die https-Methode funktioniert nicht domänenübergreifend, da https auf Port 443 wartet und ein Zertifikat erfordert. Dieser Artikel räumt mit dem Vorwurf auf, dass die Integration von sa-token dazu führen würde, dass die corsFilter-Konfiguration ungültig wird Im Internet gibt es keine Lösung für diese Situation. Bitte respektieren Sie die Originalität des Autors Original. Bitte drucken Sie die Originalquelle erneut aus. Ich hoffe, mein Beitrag kann Sie inspirieren und helfen. Bitte klicken Sie dreimal, um eine Verbindung herzustellen.