Table of contents
1. What is cross-domain
Cross-domain: browser restrictions on JavaScript’s same-origin policy.
The purpose of the same-origin policy is to ensure the security of user information and prevent malicious websites from stealing data.
Imagine this situation: Website A is a bank. After the user logs in, Website A sets a cookie on the user's machine, which contains some private information (such as the total deposit amount). After the user leaves website A, he visits website B again. If there is no origin restriction, website B can read the cookies of website A, and the private information will be leaked. What’s even more frightening is that cookies are often used to save the user’s login status. If the user does not log out, other websites can impersonate the user and do whatever they want.
The following situations are all cross-domain:
Cross-domain reason explanation |
Example |
Domain names are different |
www.jd.com give www.taobao.com |
Same domain name but different ports |
www.jd.com:8080 与 www.jd.com:8081 |
Second-level domain names are different |
item.jd.com 与 miaosha.jd.com |
If the domain name and port are the same but the request paths are different, it is not cross-domain, such as:
www.jd.com/item
www .jd.com/goods
http and https are also cross-domain
FAQ
2. Why are there cross-domain issues?
Cross-domain problems may not always occur.
Because the cross-domain problem is a security restriction of the browser for ajax requests: an ajax request initiated by a page can only be the same path as the current page domain name, which can effectively prevent cross-site attack.
Therefore: cross-domain issues are a limitation of ajax.
But this brings inconvenience to our development, and in the actual production environment, there will definitely be many servers interacting with each other, and the addresses and ports may be different. What should we do?
3. Solutions to solve cross-domain problems
1.Jsonp
- Jsonp
The earliest solution can be implemented using the cross-domain principle of script tags.
https://www.w3cschool.cn/json/json-jsonp.html
Restrictions:- Need service support
- Only GET requests can be initiated
Principle:
Jsonp is actually a cross-domain solution. It is not possible for JS to request data across domains, but it is possible for JS to request JS scripts across domains. You can encapsulate the data into a js statement and make a method call. This script can be obtained by cross-domain requesting js script. The js script will be executed immediately after getting it. Data can be passed as parameters to methods. You can get the data. This solves cross-domain issues.
2.nginx
-
nginx reverse proxy
The idea is: use nginx to make cross-domain reverse proxy non-cross-domain and support various request methods
Disadvantages: additional configuration is required in nginx, and the semantics are not clear
前端server的域名为:fe.server.com
后端服务的域名为:dev.server.com
现在我在fe.server.com对dev.server.com发起请求一定会出现跨域。
现在我们只需要启动一个nginx服务器,将server_name设置为fe.server.com,然后设置相应的location以拦截前端需要跨域的请求,最后将请求代理回dev.server.com。如下面的配置:
server {
listen 80;
server_name fe.server.com;
location / {
proxy_pass dev.server.com;
}
}
这样就可以完美绕过浏览器的同源策略了。
fe.server.com访问nginx的fe.server.com属于同源访问,而nginx对服务端转发的请求不会触发浏览器的同源策略。
3.CORS
-
CORS
Standardized cross-domain request solution, safe and reliable.
Advantages:- Control whether cross-domain is allowed on the server side, and you can customize the rules
- Support various request methods
shortcoming:
- Will generate additional requests (preflight)
3.1 What is cors
CORS is a W3C standard, whose full name is "Cross-origin resource sharing".
It allows the browser to issue XMLHttpRequest requests to cross-origin servers, thus overcoming the limitation that AJAX can only be used from the same origin.
XMLHttpRequest: The core object of Ajax
CORS needs to be supported by both the browser and the server. Currently, all browsers support this function, and IE browser cannot be lower than IE10.
- Browser side: No need to consider
Currently, all browsers support this function (not available below IE10). The entire CORS communication process is automatically completed by the browser and does not require user participation. - Server side: Make relevant settings
There is no difference between CORS communication and AJAX, so you do not need to change the previous business logic. However, the browser will carry some header information in the request. We need to use this to determine whether it is allowed to cross domain, and then add some information to the response header. This is usually done via a filter.
3.2 Principle
Preflight request
Cross-domain requests will add an HTTP query request before formal communication, called a "preflight" request (preflight).
The browser first asks the server whether the domain name of the current web page is in the server's permission list, and which HTTP verbs and header information fields can be used. Only when a positive reply is received will the browser issue a formal XMLHttpRequest request, otherwise an error will be reported.
OPTIONS /cors HTTP/1.1
Origin: http://localhost:8888
Access-Control-Request-Method: GET
Access-Control-Request-Headers: X-Custom-Header
User-Agent: Mozilla/5.0...
- Origin: It will indicate which domain the current request belongs to (protocol + domain name + port). The service will decide whether to allow cross-domain based on this value.
- Access-Control-Request-Method: The request method that will be used next, such as PUT
- Access-Control-Request-Headers: Additional header information
A sample "preflight" request:
Response to preflight request
When the service receives a preflight request, if the permission is cross-domain, it will send a response:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://localhost:8888
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
If the server allows cross-domain, the following information needs to be carried in the returned response header:
- Access-Control-Allow-Origin: Acceptable domain, which is a specific domain name or * (representing any domain name)
- Access-Control-Allow-Credentials: Whether to allow cookies to be carried. By default, cors will not carry cookies unless this value is true.
- Access-Control-Allow-Methods: Allow access methods
- Access-Control-Allow-Headers: headers allowed to be carried
- Access-Control-Max-Age: The validity period of this permission, in seconds. Ajax requests before expiration do not need to be pre-checked again.
About cookies:
In order to operate cookies, the following conditions need to be met:
- The response header of the service needs to carry Access-Control-Allow-Credentials and be true.
- When the browser initiates ajax, it needs to specify withCredentials as true
4. Steps to implement cross-domain in GateWay gateway
About the process
Build the server-gateway module
Modify the configuration pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>gmallparent</artifactId>
<groupId>com.donglin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>server-gateway</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.donglin</groupId>
<artifactId>common-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 服务注册 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 服务配置-->
<!--
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
</project>
Add the configuration file under resources
application.yml
Port 80 needs to be connected to the front-end port number (remember to check whether the registration center has api-gateway )
server:
port: 80
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.121.128:8848
gateway:
discovery: #是否与服务发现组件进行结合,通过 serviceId(必须设置成大写) 转发到具体的服务实例。默认为false,设为true便开启通过服务中心的自动根据 serviceId 创建路由的功能。
locator: #路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**,其中微服务应用名默认大写访问。
enabled: true
routes:
- id: service-product
uri: lb://service-product
predicates:
- Path=/*/product/** # 路径匹配
Cross-domain implementation in gateway
Global configuration class implementation
Package name: com.donglin.gmall.gateway.config< a i=3> CorsConfig class
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter(){
// cors跨域配置对象
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*"); //设置允许访问的网络
configuration.setAllowCredentials(true); // 设置是否从服务器获取cookie
configuration.addAllowedMethod("*"); // 设置请求方法 * 表示任意
configuration.addAllowedHeader("*"); // 所有请求头信息 * 表示任意
// 配置源对象
UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
configurationSource.registerCorsConfiguration("/**", configuration);
// cors过滤器对象
return new CorsWebFilter(configurationSource);
}
}
Startup class
package com.donglin.gmall.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServerGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ServerGatewayApplication.class,args);
}
}