Explicación súper detallada entre dominios

1. ¿Por qué existen problemas entre dominios?

Los navegadores no permiten solicitudes entre dominios porque las solicitudes entre dominios pueden causar riesgos de seguridad. La política del mismo origen es un mecanismo de seguridad del navegador que requiere que los scripts ejecutados en páginas web interactúen solo con recursos de la misma fuente (mismo protocolo, nombre de dominio y puerto).
La política del mismo origen ayuda a evitar que sitios web maliciosos roben información confidencial de los usuarios o realicen otros ataques de seguridad. Si el navegador permite solicitudes entre dominios, los sitios web maliciosos pueden acceder a datos confidenciales con otros nombres de dominio, como credenciales de inicio de sesión del usuario, archivos privados, etc., mediante la ejecución de scripts en el navegador del usuario.
Aunque las solicitudes entre dominios están restringidas por la política del mismo origen, los navegadores proporcionan algunos mecanismos para admitir la comunicación segura entre dominios, como el intercambio de recursos entre orígenes (CORS) y JSONP (JSON con relleno). A través de estos mecanismos, el servidor puede indicarle claramente al navegador qué solicitudes entre dominios son seguras y confiables, y autorizar al navegador a acceder a los recursos relevantes.
A pesar de las limitaciones de las solicitudes entre orígenes, la política del mismo origen es fundamental para proteger a los usuarios y mantener la seguridad de la red. Los desarrolladores pueden resolver problemas entre dominios utilizando proxies del lado del servidor o configurando CORS en el servidor. Esto garantiza que las solicitudes entre dominios solo se realicen en un entorno confiable y reduce los posibles riesgos de seguridad.

2. ¿Qué es el dominio cruzado?

Cuando cualquiera de los protocolos, nombres de dominio y puertos de una URL de solicitud es diferente de la URL de la página actual, se trata de dominio cruzado.

URL de la página actual URL de la página solicitada ¿Es entre dominios? razón
http://www.test.com/ http://www.test.com/index.html No Mismo origen (mismo protocolo, nombre de dominio y número de puerto)
http://www.test.com/ https://www.test.com/index.html Dominio cruzado Diferentes protocolos (http/https)
http://www.test.com/ http://www.baidu.com/ Dominio cruzado El nombre de dominio principal es diferente (prueba/baidu)
http://www.test.com/ http://blog.test.com/ Dominio cruzado Diferentes nombres de subdominio (www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ Dominio cruzado Diferentes números de puerto (8080/7001)

3. Cómo resolver problemas entre dominios

3.1 CORS (importante)

CORS (Cross-Origin Resource Sharing) es un estándar del W3C que define cómo los navegadores y los servidores deben comunicarse cuando se debe acceder a recursos de origen cruzado. La idea básica detrás de CORS es utilizar encabezados HTTP personalizados para permitir que el navegador se comunique con el servidor para determinar si la solicitud o respuesta debe tener éxito o fallar.
CORS requiere compatibilidad tanto con el navegador como con el servidor. Actualmente, todos los navegadores admiten esta función y el navegador IE no puede ser inferior a IE10.
Todo el proceso de comunicación CORS lo completa automáticamente el navegador y no requiere la participación del usuario. Para los desarrolladores, no hay diferencia entre la comunicación CORS y la comunicación AJAX de la misma fuente, y el código es exactamente el mismo. Una vez que el navegador descubre que la solicitud AJAX es de origen cruzado, automáticamente agregará información de encabezado adicional y, a veces, realizará una solicitud adicional, pero el usuario no la sentirá.
Por tanto, la clave para lograr la comunicación CORS es el servidor. Siempre que el servidor implemente la interfaz CORS, la comunicación entre orígenes es posible.
De hecho, CORS es fácil de entender. El servidor agrega un encabezado Access-Control-Allow-Origin en la respuesta HTTP: http://www.masikkk.com El valor del encabezado es el origen permitido. El navegador ve su propio origen y lo devuelve desde el servidor. Si pueden coincidir, se permite el dominio cruzado.
Los navegadores dividen las solicitudes CORS en dos categorías: solicitudes simples y solicitudes no tan simples.

3.1.1 Solicitudes simples y solicitudes no simples

(1) El método de solicitud es uno de los tres métodos siguientes:

  • CABEZA
  • CONSEGUIR
  • CORREO

(2) La información del encabezado HTTP no excede los siguientes campos:

  • Aceptar
  • Aceptar-Idioma
  • Idioma del contenido
  • ID del último evento
  • Tipo de contenido: limitado a tres valores: aplicación/x-www-form-urlencoded, multipart/form-data, text/plain

Cualquier solicitud que no cumpla las dos condiciones anteriores al mismo tiempo es una solicitud no simple.

3.1.2 El dominio cruzado implica principalmente 4 encabezados de respuesta

  • Access-Control-Allow-Origin se utiliza para establecer la dirección de origen que permite solicitudes entre dominios (las solicitudes de verificación previa y las solicitudes formales se verificarán cuando sean entre dominios)
  • Access-Control-Allow-Headers Se permite la transferencia de campos de información de encabezado especiales entre dominios (solo verificados en solicitudes de verificación previa)
  • Access-Control-Allow-Methods métodos de solicitud permitidos entre dominios o verbos HTTP (solo en la verificación de solicitud previa al vuelo)
  • Access-Control-Allow-Credentials Si se permite el uso de cookies en todos los dominios. Si desea utilizar cookies en todos los dominios, puede agregar este encabezado de respuesta de solicitud y establecer el valor en verdadero (establecerlo o no configurarlo no afectará el envío de solicitudes, pero solo afectará si las cookies deben transportarse entre dominios, pero si se configuran, se deben configurar tanto las solicitudes de verificación previa como las solicitudes formales). Sin embargo, no se recomienda usarlo entre dominios (se ha usado en el proyecto, pero es inestable y no puede ser soportado por algunos navegadores) a menos que sea necesario, porque existen muchas alternativas.

3.1.3 Proceso de procesamiento CORS de solicitud simple

Para solicitudes simples entre dominios, el navegador agregará automáticamente el campo Origen a la información del encabezado de la solicitud, indicando de qué fuente proviene la solicitud (protocolo + nombre de dominio + puerto). El servidor debe obtener este valor y luego determinar si desea aceptar esta solicitud Solicitar y devolver.

  1. Proceso de procesamiento de solicitudes simple:
    el navegador adjunta automáticamente un encabezado de origen a la solicitud entre dominios, que contiene la información de origen de la página solicitada (protocolo, nombre de dominio y puerto), para que el servidor pueda decidir si responder en función de esto. información del encabezado. Por ejemplo: Origen: http://www.masikkk.com
  2. Si el servidor cree que la solicitud es aceptable, agrega el encabezado Access-Control-Allow-Origin a la respuesta http y establece su valor en la misma información de origen que el Origen en la solicitud (si es un recurso público, usted Puede configurar * para indicar que se aceptan solicitudes de cualquier nombre de dominio). Por ejemplo: Acceso-Control-Permitir-Origen: http://www.masikkk.com
  3. Sin este encabezado o con este encabezado pero la información fuente no coincide, el navegador rechazará la solicitud. Tenga en cuenta que ni la solicitud ni la respuesta contienen información de cookies.
  4. Si necesita incluir información de cookies, la solicitud ajax debe configurar el atributo XMLHttpRequest withCredentials en verdadero y el servidor debe configurar el encabezado de respuesta Access-Control-Allow-Credentials: verdadero

3.1.4 Proceso de procesamiento CORS de solicitud compleja (solicitud de OPCIÓN primero)

Las solicitudes no simples son solicitudes que tienen requisitos especiales para el servidor, como el método de solicitud es PUT o DELETE, o el tipo del campo Tipo de contenido es aplicación/json.
Las solicitudes CORS para solicitudes complejas agregarán una solicitud de consulta HTTP antes de la comunicación formal, llamada solicitud de verificación previa (verificación previa) . La solicitud de verificación previa utiliza el método http OPCIONES** para saber si el servidor permite solicitudes entre dominios.
3395727666-7909e09b79e67694.png
Proceso de procesamiento de solicitudes complejo:

  1. El navegador envía una solicitud de verificación previa.

Antes de enviar una solicitud real, el navegador primero envía una solicitud de verificación previa al servidor. Esta solicitud utiliza el método OPCIONES, llama a la misma API y envía los siguientes encabezados: El origen debe ser el mismo que una solicitud simple y el valor es la
solicitud La información de origen de la página (protocolo, nombre de dominio y puerto)
Se requiere el método de solicitud de control de acceso El método http utilizado por la solicitud en sí, como PUT.
Access-Control-Request-Headers Opcional, información de encabezado personalizada, múltiples encabezados separados por comas.

OPTIONS /cors HTTP/1.1
Origin: https://masikkk.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
  1. El servidor devuelve una respuesta de verificación previa

Después de recibir esta solicitud, el servidor puede decidir si permite este tipo de solicitud. El servidor se comunica con el navegador enviando los siguientes encabezados en la respuesta: Se requiere
Access-Control-Allow-Origin . Igual que una solicitud simple. Permite el acceso al origen. Acepta cualquier dominio y devuelve *
Access-Control-Allow-Methods. .Obligatorio.Métodos permitidos, varios métodos separados por comas. Indica todos los métodos de solicitud entre orígenes admitidos por el servidor. Tenga en cuenta que se devuelven todos los métodos admitidos, no solo el método solicitado por el navegador. Esto es para evitar múltiples solicitudes de "verificación previa".
Access-Control-Allow-Headers El campo Access-Control-Allow-Headers es obligatorio si la solicitud del navegador incluye el campo Access-Control-Request-Headers. También es una cadena separada por comas que indica todos los campos de encabezado admitidos por el servidor, sin limitarse a los campos solicitados por el navegador en la "verificación previa".
Access-Control-Max-Age es opcional y se utiliza para especificar el período de validez de esta solicitud de verificación previa, en segundos. O durante cuánto tiempo se debe almacenar en caché esta solicitud de verificación previa.
Ejemplo de respuesta a solicitud de verificación previa:

Access-Control-Allow-Origin: http://devgou.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: NCZ
Access-Control-Max-Age: 1728000
  1. Solicitudes y respuestas normales del navegador.

Una vez que el servidor pasa la solicitud de "verificación previa", cada solicitud CORS normal posterior del navegador será igual a una solicitud simple, con un campo de encabezado Origen. La respuesta del servidor también tendrá un campo de encabezado Access-Control-Allow-Origin.

3.1.5 El marco SpringBoot implementa CORS

1. El filtro CorsFilter implementa la configuración global
@Slf4j
@Component
public class CorsFilter implements Filter {
    
    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        filterChain.doFilter(servletRequest,response);
    }
}
2. Reescriba el método addCorsMappings de WebMvcConfigurer para implementar la configuración global
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    
    
        registry.addMapping("/**")//项目中的所有接口都支持跨域
                .allowedOrigins("*")//所有地址都可以访问,也可以配置具体地址
                .allowCredentials(true)
                .allowedMethods("*")//"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"
                .maxAge(3600);// 跨域允许时间
    }
}
3. Configuración local de anotación @CrossOrigin

Agregue directamente métodos o clases@CrossOrigin para resolver problemas entre dominios

/**
 * Created with IDEA
 *
 * @Description xxxx控制层
 * @Version 1.0
 */
@RestController
@CrossOrigin
@RequestMapping("/situation")
public class SituationController extends PublicUtilController {
    
    
 
    @Autowired
    private SituationService situationService;
    // log日志信息
    private static Logger LOGGER = Logger.getLogger(SituationController.class); 
}

3.2 Proxy inverso de Nginx (importante)

Usar el proxy inverso nginx para lograr dominios cruzados es el método de dominio cruzado más simple. Solo necesita modificar la configuración de nginx para resolver problemas entre dominios. Es compatible con todos los navegadores y sesiones. No es necesario modificar ningún código y no afectará el rendimiento del servidor.
Solo necesitamos configurar nginx y configurar múltiples prefijos en un servidor para reenviar solicitudes http/https a múltiples servidores reales. De esta forma, todas las URL de este servidor tienen el mismo nombre de dominio, protocolo y puerto. Por lo tanto, para los navegadores, estas URL son del mismo origen y no existen restricciones entre dominios. Y, en realidad, estas URL son atendidas por servidores físicos. El javascript dentro de estos servidores puede llamar a URL en todos estos servidores en todos los dominios.
Operación específica:
use nginx para reenviar solicitudes.
Varios parámetros que deben configurarse en nginx:

Access-Control-Allow-Origin:必含,允许的域名,只能填通配符或者单域名
Access-Control-Allow-Methods:必含,允许跨域请求的 http 方法
Access-Control-Allow-Headers:返回支持的 http 请求头
Access-Control-Allow-Credentials:可选,标志着当前请求是否包含 cookies 信息,布尔值。只有一个可选值:true,如果不包含 cookies,请略去该项,而不是填 false。这一项与XmlHttpRequest 对象当中的 withCredentials 属性应保持一致,即 withCredentials 为true时该项也为 true;withCredentials为false时,省略该项不写。反之则导致请求失败。
Access-Control-Max-Age:可选,以秒为单位的缓存时间,用于缓存预检请求。
http {
  ......
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Headers X-Requested-With;
  add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
  ......
}
server {
	listen       80;
	server_name  xxx.com;
 
	location /xxx-web/papi {
		add_header 'Access-Control-Allow-Origin' $http_origin;
		add_header 'Access-Control-Allow-Credentials' 'true';
		add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
		add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
		add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
		if ($request_method = 'OPTIONS') {
			add_header 'Access-Control-Max-Age' 1728000;
			add_header 'Content-Type' 'text/plain; charset=utf-8';
			add_header 'Content-Length' 0;
			return 204;
		}
		root   html;
		index  index.html index.htm;
		proxy_pass http://127.0.0.1:7071;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_connect_timeout 5;
	}
 
	location /xxx-web {
		add_header 'Access-Control-Allow-Origin' $http_origin;
		add_header 'Access-Control-Allow-Credentials' 'true';
		add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
		add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
		add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
		if ($request_method = 'OPTIONS') {
			add_header 'Access-Control-Max-Age' 1728000;
			add_header 'Content-Type' 'text/plain; charset=utf-8';
			add_header 'Content-Length' 0;
			return 204;
		}
		root   html;
		index  index.html index.htm;
		proxy_pass http://127.0.0.1:8080;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_connect_timeout 5;
	}
 
	location / {
		root   /var/www/xxx/wechat/webroot;
		index  index.html index.htm;
	}
 
	error_page   500 502 503 504  /50x.html;
	location = /50x.html {
		root   html;
	}
}

La diferencia entre estas dos configuraciones radica en la granularidad y el alcance de la configuración entre dominios. La primera parte de la configuración establece la configuración global entre dominios en el bloque "http", utilizando el carácter comodín
"*", lo que significa que se permiten solicitudes de todas las fuentes para el acceso entre dominios. Establece
los campos "Access-Control-Allow-Origin", "Access-Control-Allow-Headers" y
"Access-Control-Allow-Methods"
en el encabezado de respuesta para especificar nombres de dominio y solicitar encabezados que permitan el acceso entre dominios. y métodos de solicitud. Esta configuración tendrá efecto en todas las solicitudes del servidor, incluidos todos los bloques de "ubicación".
La segunda parte de la configuración establece la configuración entre dominios en un bloque de "ubicación" específico. Solo tiene efecto para rutas de solicitud que comienzan con "/api". Esta configuración establece
los campos "Access-Control-Allow-Origin", "Access-Control-Allow-Headers" y
"Access-Control-Allow-Methods"
en el encabezado de respuesta, y establece más detalles para la ruta de solicitud específica. nombres de dominio, encabezados de solicitud y métodos de solicitud. Para otras rutas de solicitud, como la ruta raíz "/", estas configuraciones entre dominios no se aplicarán.
Por lo tanto, la primera configuración es una configuración global entre dominios y se aplica a todo el servidor, mientras que la segunda configuración es una configuración entre dominios bajo una ruta específica y solo se aplica a la ruta "/api".
En términos generales, si solo necesita permitir el acceso entre dominios para solicitudes de todas las fuentes, puede usar la primera configuración. Si necesita establecer políticas entre dominios más detalladas para interfaces o rutas específicas, puede utilizar la segunda etapa de configuración. El método de configuración debe seleccionarse según sus necesidades y escenarios de aplicación.

Si solo responde a solicitudes simples y no utiliza cookies, simplemente configure Access-Control-Allow-Origin como el nombre de dominio de front-end. Por ejemplo, solo se
permite el acceso a http://devgou.com, puede configurarlo como sigue:

add_header 'Access-Control-Allow-Origin' 'http://devgou.com';

Si necesitas permitir el acceso desde cualquier dominio, puedes configurarlo así

add_header Access-Control-Allow-Origin *;

Si no desea permitir todo pero necesita permitir varios nombres de dominio, debe usar la directiva de mapa nginx.
Por ejemplo, desea permitir el acceso a cuatro nombres de dominio en el siguiente mapa:

http {
  map $http_origin $corsHost {
    default 0;
    "~http://madaimeng.com" http://madaimeng.com;
    "~http://devgou.com" http://devgou.com;
    "~http://masikkk.com" http://masikkk.com;
    "~http://localhost:4000" http://localhost:4000;
  }

  server {
    listen       80;
    server_name  api.masikkk.com api.madaimeng.com api.devgou.com;

    location / {
      add_header 'Access-Control-Allow-Origin' $corsHost;
      proxy_pass http://localhost:8001;
    }
  }
}

Resumir:

  • La política del mismo origen es un estándar que los navegadores deben seguir, pero si el servidor realiza una solicitud al servidor, no es necesario seguir la política del mismo origen.
  • CORS admite todo tipo de solicitudes HTTP y es la solución fundamental para solicitudes HTTP entre dominios.
  • En el trabajo diario, las soluciones entre dominios más utilizadas son el proxy inverso cors y nginx.
  • En una palabra, las restricciones de seguridad entre dominios del navegador requieren una adaptación del lado del servidor.

referencia:

  1. https://www.jianshu.com/p/cedc8b1cd84c
  2. https://www.qiufeng.blue/frontend/cors.html

Supongo que te gusta

Origin blog.csdn.net/hansome_hong/article/details/131577084
Recomendado
Clasificación