le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Si prega di fare riferimento al seguente articolo per il motivo: Il modo corretto per risolvere i problemi tra domini separando il front-end e il back-end di sa-token
https://mp.weixin.qq.com/s/96WbWL28T5_-xzyCfJ7Stg
https://blog.csdn.net/qq_34905631/article/details/140233780?spm=1001.2014.3001.5501
Sebbene questo articolo abbia trovato la postura corretta dopo molti tentativi, la causa principale del problema non è stata trovata. Quindi, dopo aver riflettuto ed esplorato, mi sono chiesto se questo dominio incrociato potesse essere simulato localmente e ho iniziato a cercarlo Wang, lo staff front-end del progetto, ha quindi effettivamente simulato il cross-domain locale. Nel progetto, ha separato il front-end e il back-end sa-token precedenti per risolvere la corretta postura del cross-domain e ha riprodotto il problema. dopo aver commentato SimpleCORSFilter nell'articolo.
La configurazione interdominio di spring5.2.15.RELEASE mvc ufficiale è la seguente:
https://docs.spring.io/spring-framework/docs/5.2.15.RELEASE/spring-framework-reference/web.html#mvc-cors-intro
Segui il metodo ufficiale collegato sopra, quindi aggiungi una classe CustomCorsFilter come segue:
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;
}
}
È stato verificato che la configurazione di CustomCorsFilter è valida in un progetto su cui ho lavorato. Tuttavia, in un progetto recente, è inutile utilizzare questa configurazione della classe CustomCorsFilter per risolvere problemi tra domini. Questa configurazione non è valida? Nell'articolo precedente sul modo corretto di risolvere i problemi tra domini separando il front-end e il back-end sa-token, la verifica della classe CustomCorsFilter non era effettivamente valida. Questo problema era davvero sconcertante quando ho riconfigurato la classe CustomCorsFilter nel progetto , (SimpleCORSFilter deve essere commentato, perché questo SimpleCORSFilter può essere utilizzato dopo la verifica). Dopo aver eseguito il progetto localmente, il front-end simula le richieste tra domini ho inserito un punto di interruzione nel seguente codice della classe CorsFilter:
@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);
}
Inserisci anche un punto di interruzione sul metodo CorsUtils.isPreFlightRequest:
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);
}
Quindi lo screenshot del punto di interruzione è il seguente:
L'interfaccia di accesso è una richiesta complessa tra domini con http più nome di dominio e verrà inviata una richiesta di pre-rilevamento (richiesta OPTIONS).
Nel progetto integrato con sa-token, ho impostato un breakpoint sul metodo doFilterInternal di OncePerRequestFilter e ho trovato i seguenti filtri:
Si può vedere che il CustomCorsFilter che abbiamo personalizzato sopra viene eseguito per primo, e i due filtri relativi a sa-token: saPathCheckFilterForServlet e SaServletFilter vengono eseguiti successivamente, quindi altre congetture precedenti sono state ben confermate Il punto di interruzione va al metodo doFilterInternal di CorsFilter di seguito :
//关键就是这里,在这里打上断点
if (!isValid || CorsUtils.isPreFlightRequest(request)) {
return;
}
Il problema risiede nel seguente codice:
CorsUtils.isPreFlightRequest(request)
Questa riga di codice ha restituito true, quindi tutti i filtri successivi non sono stati eseguiti, quindi la richiesta non è riuscita a raggiungere l'interfaccia segnalava ancora problemi tra domini. Quindi ho eseguito il debug della riga di codice CorsUtils.isPreFlightRequest(request). , si è riscontrato che dopo che una richiesta complessa inviava una richiesta di pre-rilevamento (richiesta OPTIONS) tra domini, l'origine veniva impostata in modo inspiegabile:
http://localhost:3000
Questo era molto strano, quindi ho chiesto al mio collega front-end Lao Wangbang di verificare dove era impostato questo valore e ho trovato quanto segue:
Il front-end non imposta Origin, ma imposta solo i seguenti parametri:
//设置axios跨域访问
axios.defaults.withcredentials = true // 设置cross跨域 并设置访问权限 允许跨域携带cookie信息axios.defaults.crossDomain=true //设置axios跨域的配置
Nell'immagine sopra, c'è un solo valore Referer che coincide con il valore Origin. È davvero solo una coincidenza, quindi ho letto il seguente articolo:
https://blog.csdn.net/qq_55316925/article/details/128571809
Mi ha dato molte idee, quindi ci ho pensato e ho scoperto che CustomCorsFilter configurato sul backend era efficace. Posso modificare il codice sorgente di CorsFilter Quindi ho provato i due metodi seguenti, che sono stati verificati da me e il front-end Lao Wang, entrambi i metodi sono fattibili e entrambi possono risolvere il problema cors tra domini.
Modifica il codice sorgente CorsFilter sul backend
Aggiungi un nuovo pacchetto org.springframework.web.filter in src.main.java nel progetto
Quindi copia il codice sorgente di CorsFilter e inseriscilo nel pacchetto org.springframework.web.filter appena creato sopra, quindi puoi modificare il codice sorgente di CorsFilter.
/*
* 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);
}
}
Aggiungi il seguente codice al front-end: disabilita o rimuovi la policy referrer-policy`
https://blog.csdn.net/qq_49810363/article/details/111036180
Il nuovo codice è il seguente:
<meta name="referrer" content="never">
La politica di referrer del browser è anche per motivi di sicurezza. Il browser che utilizzo è il browser Chrome.
Dopo continui tentativi e tentennamenti, il problema della distribuzione interdominio cors si è verificato dopo l'integrazione di sa-token nel progetto. In generale, le specifiche del protocollo interdominio cors non consentono questa operazione. Inoltre, il browser e The back La libreria di soluzioni -end non consente operazioni di richiesta che non seguono le specifiche del protocollo cors tra domini, quindi è possibile utilizzare sa-token per separare le soluzioni front-end e back-end per la corretta postura delle soluzioni tra domini Configurare un SimpleCORSFilter, scrivere parametri specifici ed elaborare La richiesta di pre-rilevamento restituisce un codice di stato 200 oppure è possibile utilizzare uno dei due metodi in questo articolo per risolvere il problema tra domini cors. La soluzione in questo articolo è questa Ne eseguo il debug dopo aver riprodotto la richiesta tra domini nel punto di interruzione Soluzione, se ritieni di poter seguire il metodo in questo articolo, riproduci la richiesta tra domini localmente e quindi esegui il debug del punto di interruzione per vedere se si tratta di un problema. la riga CorsUtils.isPreFlightRequest(request) di corsFilter. In generale, questo cors Il problema tra domini è un grosso problema per i browser Una semplice richiesta a corsFilter non fallirà. Una richiesta complessa invia una richiesta di pre-rilevamento (richiesta OPTIONS). Poiché la policy referrer del browser conterrà un valore, dopo l'elaborazione back-end, questo valore verrà assegnato all'attributo Origin dell'intestazione della richiesta, facendo sì che la riga di codice CorsUtils.isPreFlightRequest(request) di corsFilter restituisca true. e quindi ritorna. Di conseguenza, il doFilter della serie successiva di filtri non viene eseguito e non è possibile accedere all'interfaccia back-end e la pagina del browser front-end segnala ancora problemi tra domini , questo problema è davvero fastidioso. Il metodo https non funziona tra domini, perché https ascolta la porta 443 e richiede un certificato. Immagino che ciò richieda la configurazione del certificato. Questo articolo chiarisce l'accusa secondo cui l'integrazione di sa-token renderà non valida la configurazione di corsFilter è lo stesso su Internet. Nessuno degli articoli in questo articolo ha una soluzione a questa situazione. Va detto che è il primo. Si prega di rispettare l'originalità dell'autore originale. Ristampa e aggiungi la fonte originale. Questa condivisione termina qui. Spero che la mia condivisione possa ispirarti e aiutarti. Fai clic tre volte per connetterti, ok!