Directorio de artículos
- Solución de problemas de dominios cruzados de Java
-
- 1. ¿Qué es el dominio cruzado?
- 2. Ejemplos comunes de dominios cruzados
- 3. Solución de back-end de Java
-
- 1. Implementar WebMvcConfigurer
- 2. Interceptor del manipulador de implementos
- 3. Usar filtro
- 4. Use la anotación @CrossOrigin para lograr
- 5. Agregue campos como Access-Control-Allow-Origin en el encabezado de respuesta
- 6. Usa la configuración de Nginx
- 7. Configurar el enrutamiento de la puerta de enlace
Solución de problemas de dominios cruzados de Java
1. ¿Qué es el dominio cruzado?
Cross-domain se refiere a: los navegadores no pueden ejecutar scripts de otros sitios web, y cuando solicitan recursos de otro nombre de dominio desde una página web de un nombre de dominio, cualquier diferencia en el nombre de dominio, puerto o protocolo es cross-domain. El cruce de dominios es causado por la política del mismo origen del navegador, que es una restricción de seguridad impuesta por el navegador. La página A quiere obtener los recursos de la página B. Si los protocolos, los nombres de dominio, los puertos y los nombres de subdominio de las páginas A y B son diferentes, las acciones de acceso realizadas son todas entre dominios.
2. Ejemplos comunes de dominios cruzados
URL de la página actual | URL de la página solicitada | Ya sea entre dominios | razón |
---|---|---|---|
http://www.test.com/ | http://www.test.com/index.html | No | Misma fuente (mismo protocolo, nombre de dominio, número de puerto) |
http://www.test.com/ | https://www.test.com/index.html | dominio cruzado | El protocolo es diferente (http/https) |
http://www.test.com/ | http://www.baidu.com/ | dominio cruzado | El nombre de dominio es diferente (prueba/baidu) |
http://www.test.com/ | http://blog.test.com/ | dominio cruzado | El nombre de dominio es diferente (www/blog) |
http://www.test.com:8080/ | http://www.test.com:7001/ | dominio cruzado | Diferentes números de puerto (8080/7001) |
3. Solución de back-end de Java
1. Implementar WebMvcConfigurer
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")// 拦截所有的请求
.allowedOrigins("*")// 可跨域的域名,*为所有
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")// 允许跨域的方法,可以单独配置
.maxAge(3600);
}
}
2. Interceptor del manipulador de implementos
Cree una clase que implemente la interfaz HandlerInterceptor y configure el encabezado de respuesta en el método preHandle para lograr un dominio cruzado.
@Component
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
return true;
}
// ...
}
```
这将允许来自 http://example.com 的跨域请求访问应用程序中的 API。
3. Usar filtro
Cree una clase que implemente la interfaz javax.servlet.Filter y configure el encabezado de respuesta en el método doFilter para lograr un dominio cruzado.
@WebFilter
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(req, res);
}
// ...
}
````
这将允许来自 http://example.com 的跨域请求访问应用程序中的 API。
Nota : cuando se usa Filter para implementar cross-domain, Filter interceptará todas las solicitudes, no solo las de cross-domain. Por lo tanto, debe tener cuidado al configurar encabezados de respuesta para evitar afectar el procesamiento normal de otras solicitudes. Si se requiere un control más detallado, considere usar la anotación o los interceptores @CrossOrigin.
4. Use la anotación @CrossOrigin para lograr
Al usar Spring Boot para implementar dominios cruzados, puede usar la anotación @CrossOrigin proporcionada por Spring para configurar el acceso entre dominios. Los pasos específicos de implementación son los siguientes:
(1) Agregue la anotación @CrossOrigin a la clase o método del controlador que necesita implementar el dominio cruzado. Por ejemplo:
@CrossOrigin(origins = "http://example.com")
@RestController
public class MyController {
// ...
}
```
这将允许来自 http://example.com 的跨域请求访问 MyController 中的方法。
(2) Si es necesario permitir el acceso a varios nombres de dominio, el parámetro origins se puede establecer en una matriz que contenga todos los nombres de dominio a los que se permite el acceso. Por ejemplo:
@CrossOrigin(origins = {
"http://example1.com", "http://example2.com"})
@RestController
public class MyController {
// ...
}
```
(3) Si necesita permitir métodos HTTP entre dominios que no sean GET y POST, puede usar el parámetro de métodos para especificar la lista de métodos permitidos. Por ejemplo:
@CrossOrigin(origins = "http://example.com", methods = {
RequestMethod.GET, RequestMethod.POST})
@RestController
public class MyController {
// ...
}
```
(4) Si necesita permitir encabezados de solicitud entre dominios que no sean Content-Type, puede usar el parámetro allowHeaders para especificar la lista de encabezados de solicitud permitidos. Por ejemplo:
@CrossOrigin(origins = "http://example.com", allowedHeaders = {
"Content-Type", "Authorization"})
@RestController
public class MyController {
// ...
}
```
(5) Si necesita permitir el envío de información de autenticación, puede usar el parámetro allowCredentials para establecerlo en verdadero. Por ejemplo:
@CrossOrigin(origins = "http://example.com", allowCredentials = "true")
@RestController
public class MyController {
// ...
}
```
5. Agregue campos como Access-Control-Allow-Origin en el encabezado de respuesta
(1) Agregue el campo Access-Control-Allow-Origin en el encabezado de respuesta para permitir el acceso de nombres de dominio específicos. Por ejemplo, el siguiente código permitirá que el nombre de dominio http://example.com acceda a la API:
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
```
如果希望允许所有域名访问 API,可以将值设置为 *:
(2) Si necesita permitir que varios nombres de dominio accedan a la API, puede agregar el campo Access-Control-Allow-Origin en el encabezado de respuesta y configurarlo en una lista que contenga todos los nombres de dominio a los que se les permite acceder. Por ejemplo:
response.setHeader("Access-Control-Allow-Origin", "http://example1.com, http://example2.com");
```
(3) Si necesita permitir métodos HTTP entre dominios que no sean GET y POST, puede agregar el campo Access-Control-Allow-Methods en el encabezado de respuesta para especificar la lista de métodos permitidos. Por ejemplo:
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
```
(4) Si necesita permitir encabezados de solicitud entre dominios que no sean Content-Type, puede agregar el campo Access-Control-Allow-Headers en el encabezado de respuesta para especificar la lista de encabezados de solicitud permitidos. Por ejemplo:
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
```
(5) Si utiliza una solicitud con información de autenticación, como una solicitud con Cookie, debe agregar el campo Access-Control-Allow-Credentials en el encabezado de respuesta y establecerlo en verdadero, lo que indica que la información de autenticación puede ser enviado Por ejemplo:
response.setHeader("Access-Control-Allow-Credentials", "true");
```
最后,需要将这些响应头添加到每个需要跨域访问的 API 的响应中。
6. Usa la configuración de Nginx
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
if ($request_method = 'OPTIONS') {
return 204;
}
}
Si utiliza una solicitud con información de autenticación, como una solicitud con Cookie, debe configurar el campo Access-Control-Allow-Credentials en verdadero, lo que significa que se permite enviar información de autenticación. Por ejemplo:
add_header 'Access-Control-Allow-Credentials' 'true';
Si se usa el balanceo de carga en la parte superior de Nginx, la configuración anterior debe agregarse al bloque del servidor de balanceo de carga. Si se utiliza un proxy inverso, la configuración anterior también debe agregarse al bloque del servidor del proxy inverso.
7. Configurar el enrutamiento de la puerta de enlace
- id: my_route
uri: http://localhost:8080
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>.*), /$\{
segment}
- AddResponseHeader=Access-Control-Allow-Origin:http://example.com
- AddResponseHeader=Access-Control-Allow-Methods:GET, POST, PUT, DELETE
- AddResponseHeader=Access-Control-Allow-Headers:Content-Type, Authorization
- AddResponseHeader=Access-Control-Allow-Credentials:true
`````
这将允许来自 http://example.com 的跨域请求访问 Gateway 中的 API。
Si utiliza una solicitud con información de autenticación, como una solicitud con Cookie, debe configurar el campo Access-Control-Allow-Credentials en verdadero, lo que significa que se permite enviar información de autenticación. Por ejemplo:
- AddResponseHeader=Access-Control-Allow-Credentials:true
`````
最后,需要将这些配置添加到每个需要跨域访问的 API 的路由配置中。
需要注意的是,如果在 Gateway 的路由中使用了负载均衡,需要在负载均衡的路由配置中添加以上配置。如果使用了反向代理,也需要在反向代理的路由配置中添加以上配置。