What are the three kinds of cross-domain cross-domain & Solutions

The so-called homologous (referring to a domain in the same) is two pages have the same protocol (protocol), the host (host) port number (port)

Origin policy is a security feature browser client script different sources in the absence of express authorization, can not read and write other resources. Same Origin Policy is the cornerstone of the browser security

Origin policy prevents a domain javascript script and content to another domain interact. Such as office and external network environment, when we visit a malicious Web site outside the network, the malicious Web site will use ajax request url send our inward host network, destroy or steal data

A non-homologous browser limitations as well as three kinds Solutions

Non-homologous limit

  1. Can not read non-homologous pages of Cookie, LocalStorage and IndexedDB
  2. No access to non-homologous pages DOM
  3. AJAX request can not be sent to non-homologous address, XHR requests

Cross-domain Solutions 1-- limit to avoid non-homologous

  1. Let the browser does not limit, specify the parameters and let the browser do the check, but the method is not reasonable, because it requires everyone to do changes
  2. Do not make XHR requests, so even if the cross-domain, there will be no non-homologous browser restrictions, the solution is JSONP, create a script by dynamic, a request by script

Cross-domain Solutions 2 - Cross-Origin Resource Sharing Scheme

  1. According to W3C Cross-Origin Resource Sharing program, and modify the code in the called party, plus field that tells the browser that supports cross-domain site

Cross-domain Solutions 3 - Hidden across domains

  1. Use Nginx reverse proxy, reverse proxy using the domain name in a domain name to point b inside of address request, so that the browser has been visiting a website, does not trigger a cross-domain restrictions

Two, JSONP

  • Common request value XHR, we want content-type is typically returned from the server json
  • JSONP request issued by a script, want the return is js script

Content-Type refers to the content when the coding type of http / https send information to the server, the HTTP protocol header, a Content-Type media types represented in the request and response information. It is used to tell the server how to handle data requests, and tells the client (usually a browser) how to parse the response data, such as display pictures, parse and display html and so on.

Not unique request or response parameters

a JSONP principle

With JQuery, for example, send ajax request when set up dataType:"jsonp", will use JSONP calls the function, url function into a myurl?callback=e5bbtttform, e5bbttt is a temporary method name, based on the back-end callbackof the value returned by a js script, such as

<script>
    e5bbttt({"a":"aaa","b":"bbb"});
</script>

JQuery will advance to generate a temporary function in accordance with the contents ajax success, the name is xxx

$.ajax({
    // 其他省略
    dataType:"jsonp",
    success:function(data){
        console.log(data.a);
        console.log(data.b);
    },
    jsonp:"e5bbttt"
})

// JQuery 生成的临时函数
function e5bbttt(data){
    ajaxObject.success(data);
}

The server returned to the client e5bbttt({"a":"aaa","b":"bbb"});, which is equivalent to call immediately (?) Called JQuery generation e5bbtttfunction, used this function is destroyed (?)

JSONP can be considered a convention of "agreement", callback is conventional definition of a temporary function name as a parameter. If you want to customize the parameter name, using ajax need jsonp attribute definition.

b JSONP drawbacks

  1. Require changes to the code server
  2. Only supports GET requests
  3. Not sending a request xhr
  4. Unsafe

Third, the backend solve cross-domain

With related user data request is dynamic, not static data requests, such as css js, so, HTTP server (Apache, Nginx, etc.) to do a role in at least two

  • HTTP server, handle static requests
  • Reverse proxy, load balancing

On the server side to solve cross-domain there are two kinds Solutions

  • In the back-end application solution is called: Add the specified field in the response header that tells the browser allows the caller. Request this solution is sent from the browser to back-end server, the browser will see the url directly b.com
  • In the front-end server Solution: This is a hidden cross-domain solutions. This cross-domain requests are not sent directly from the browser, but forward, to see in the browser or a.com from the middle past the url http server (where the front-end application server), it will not be considered to be cross area. But the request to b.com b.com or will to

a cross-domain principle and back-end Solutions

Based browser same-origin policy, non-homologous script inoperable other sources below target. The object you want to operate under other sources will need cross-domain. To sum up, in the same-origin policy restrictions, can not send ajax request between non-homologous sites. If necessary, it can be achieved by reducing the field or other techniques.

In order to solve the problem of cross-domain browser, W3C proposed cross-origin resource sharing program that CORS (Cross-Origin Resource Sharing).

CORS possible without destroying the regular i.e., back-end server implements CORS interfaces, cross-domain communication can be achieved.

CORS request into two categories: a simple and non-simple request requests, respectively, provides support for cross-domain communication.

1 simple request

  1. CORS occur before, sending an HTTP request can not contain any custom fields in the message header, HTTP header information and does not exceed the following fields:
    1. Accept
    2. Accept-Language
    3. Content-Language
    4. Last-Event-ID
    5. Content-Type is only these three
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain
  2. GET HEAD POST request method is 1 and satisfy the condition

A simple request:

GET /test HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, sdch, br
Origin: http://www.test.com
Host: www.test.com

For a simple request, CORS Origin strategy is to add a request field in the request header, a field indicating the request issued. After the server receives the request, according to the field determines whether to permit the access request.

  • If allowed, then add Access-Control-Allow-Origin field in the HTTP header information, and returns the correct result
  • If not, Access-Control-Allow-Origin field is not added

In addition Access-Control-Allow-Origin mentioned above, there are several fields used to describe the results returned CORS

  • Access-Control-Allow-Credentials: Alternatively, if the user can send, cookie handling
  • Access-Control-Expose-Headers: optional, allowing users to get the field. There are several fields whether or not to allow cross-domain can get: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma

2 non-simple request

Usually ajax request sending JSON format or with custom request header

For cross-origin requests are not simple request, the browser will request before the real issue, increase the time OPTION request, called preflight request (preflightrequest). Request information is true preflight request includes a request method, custom header field, a source of information to the HTTP header information field, asks the server whether to allow such operations

For example, a preflight request GET request includes a custom parameter X-Custom-Header

OPTIONS /test HTTP/1.1
Origin: http://www.test.com
Access-Control-Request-Method: GET // 请求使用的 HTTP 方法
Access-Control-Request-Headers: X-Custom-Header // 请求中包含的自定义头字段
Host: www.test.com

When the server receives a request, it is necessary to separately Origin, Access-Control-Request-Method, Access-Control-Request-Headers for authentication, after the verification, is added in the HTTP header information return:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.test.com // 允许的域
Access-Control-Allow-Methods: GET, POST, PUT, DELETE // 允许的方法
Access-Control-Allow-Headers: X-Custom-Header // 允许的自定义字段
Access-Control-Allow-Credentials: true // 是否允许用户发送、处理 cookie
Access-Control-Max-Age: 172800 // 预检请求的有效期,单位为秒。有效期内,不需要发送预检请求,ps 48小时

When the preflight request by the browser will send the request to the real server. This realization of cross-domain requests access to the resource.

So back-end processing is actually processing the preflight request

== Note: ==

== in Chrome and Firefox, if Access-Control-Allow-Methods are not allowed to GET / POST / HEAD requests, but allows cross-domain, and browsers will allow GET / POST / HEAD these simple requests access, then Method must ban these other approaches in the background ==

b backend application treatment - Filter & HttpServletResponse Method

This method does not use Spring, can also be used for Servlet

Configuration in web.xml

<!-- 跨域 -->
<filter>
    <filter-name>webFliter</filter-name>
    <filter-class>com.n031.filter.WebFliter</filter-class>
</filter>
<filter-mapping>
    <filter-name>webFliter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Write java class

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class WebFliter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse res = (HttpServletResponse) response;
        // 允许跨域的域名,设置*表示允许所有域名
        String origin = req.getHeader("Origin");
        if ("abcdefg".contains(origin)) {  // 满足指定的条件
            res.addHeader("Access-Control-Allow-Origin", origin);
        }
        res.addHeader("Access-Control-Allow-Origin", "http://www.test.com");
        // 允许跨域的方法,可设置*表示所有
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        // 允许的自定义字段
        String headers = req.getHeader("Access-Control-Request-Headers"); // 获取 request 发来的自定义字段
        res.addHeader("Access-Control-Allow-Headers", headers);
        // 或者
        // res.addHeader("Access-Control-Allow-Headers", "X-Custom-Header");
        // 预检请求的有效期,单位为秒。有效期内,不需要发送预检请求,ps 48小时
        res.addHeader("Access-Control-Max-Age", "172800");
        // 还可以有其他配置...
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

}

c backend application processing - Spring Method

Spring are many ways to solve cross-domain, fennel and feeling the same written word in five. Not all listed here.

Look under the principle.To be honest though do not understand why, but looked at the source code for this class is indeed so written.

Essentially constructed CorsConfigurationand commissioned to DefaultCorsProcessorimplement (chain of responsibility pattern, a lot of things to learn ah ...)

public class CorsConfiguration {
    private List<String> allowedOrigins;
    private List<String> allowedMethods;
    private List<String> allowedHeaders;
    private List<String> exposedHeaders;
    private Boolean allowCredentials;
    private Long maxAge;
}

DefaultCorsProcessorThe processRequestprocessing steps are as follows spring-web 5.1.8-RELEASE( )

  1. Origin is included to determine whether the field is not included on the release, otherwise continues to judge
  2. Determining whether the Response Header already contains Access-Control-Allow-Origin. If it does, the proof has been treated, released, or continue to judge
  3. Homologous to determine whether, and if so then released, otherwise continues to judge
  4. This step basically have come to this conclusion is a cross-domain requests. Then look at the CORS configuration rules
    • It is not configured, and is a preflight request, the request is denied (cross-domain description of the prohibited application)
    • It is not configured, and not preflight request, the processing skips across domains (return data may cause the intercepted browser)
    • Configured, based on configured rules ( CorsConfiguration) decide whether to release

1 Add @CrossOrigin comment on the Controller

For the case of this embodiment requires only one or two interfaces rest or no cross-domain gateway, this approach is very simple and suitable for modifying the original group code, based on a relatively small impact.

@CrossOrigin(allowCredentials = "true", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE}, origins = "*")
@PostMapping("/abc")
public String handler(@RequestBody String json) {
    return "abc";
}

2 increase in global configuration WebMvcConfigurer

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")// 允许跨域的访问路径
            .allowedOrigins("*")// 允许跨域访问的源
            .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")// 允许请求方法
            .maxAge(172800)// 预检间隔时间
            .allowCredentials(true);// 是否允许发送 cookie
    }
}

Note Because Java8 began to support the default method, this class from the beginning of spring 5.0 has expired, the future of this method will be transferred to WebMvcConfigurerthe interface

default void addCorsMappings(CorsRegistry registry){}

3 Use in conjunction with Filter

In fact, a similar method and are constructedCorsConfiguration

@Configuration
public class CorsConfig {
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration config = new CorsConfiguration();
        // 是否发送cookie
        config.setAllowCredentials(true);
        // 允许的网站域名,全允许则设为 *
        config.addAllowedOrigin("http://localhost:8088");
        // 允许 HEADER 或 METHOD , * 为全部
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        // 这个顺序很重要,为避免麻烦请设置在最前
        bean.setOrder(0);
        return bean;
    }
}

If more than one such scheme micro-services and more, plus the need to have such a piece of code in the main class for each service, increasing the amount of maintenance.

These three solutions are implemented in the program on the basis of SpringBoot, in case more difficult to maintain the interface module or more.

Since Spring Cloud comes with Gateway, the following will talk about the cross-domain solutions using the Gateway. (Gateway to replaceConstantly bouncing Zuul's next-generation gateways)

4 In the Gateway interceptor increase CorsFilter

== 45 unverified method ==

This approach is somewhat similar with Option III, just put the Gateway end, for the case of multiple micro-services modules circumstances, greatly reducing the amount of code SpringBoot end module, allowing each module to do more to focus on the business logic implementation. This program only need to add the code Filter class to the Gateway Lane.

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;

@Configuration
public class CorsWebFilter implements WebFilter {

    private static final String ALL = "*";
    private static final String MAX_AGE = "18000";

    @Override
    public Mono<Void> filter(ServerWebExchange ctx, WebFilterChain chain) {
        ServerHttpRequest request = ctx.getRequest();
        String path = request.getPath().value();
        ServerHttpResponse response = ctx.getResponse();
        if ("/favicon.ico".equals(path)) {
            response.setStatusCode(HttpStatus.OK);
            return Mono.empty();
        }

        if (!CorsUtils.isCorsRequest((HttpServletRequest) request)) {
            return chain.filter(ctx);
        }

        HttpHeaders requestHeaders = request.getHeaders();
        HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
        HttpHeaders headers = response.getHeaders();
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
        headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
        if (requestMethod != null) {
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
        }
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
        headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);

        if (request.getMethod() == HttpMethod.OPTIONS) {
            response.setStatusCode(HttpStatus.OK);
            return Mono.empty();
        }
        return chain.filter(ctx);
    }
}

5 Modify the Gateway Profile

Gateway carefully read the document you will find the original CorsFilter already in the Gateway again, and do not need to write their own code to achieve, but also more flexible, you can modify the configuration file, use in combination distribution center, enables dynamic modification.

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "docs.spring.io"
            allowedMethods:
              - GET

d backend server processing - Ngnix Method

Nginx here to make do reverse proxy functionality, browser to access the page on a.com Nginx, ajax request interface is b.com, it is considered to be cross-domain browser

Nginx with on nginx.conf (vhost is agreed practice, this does not modify the master file)

include vhost/*.config;

Creating cors.conf

server{
    listen 80; // 监听80端口
    server_name b.com; // 监听向 b.com 发送的请求
    location /{
        proxy_pass http://ser432ver.53253bb.com:8080; // 转发到哪里

        // Filter实现的功能在Nginx上再实现一遍

        add_header Access-Control-Allow-Origin $http_origin; // $http_ 可以获取请求中相应的 header 参数
        add_header Access-Control-Allow-Method *;
        add_header Access-Control-Allow-Headers X-Custom-Header;
        // 或者
        // add_header Access-Control-Allow-Headers $http_access_control_request_headers;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Max-age 172800;

        // 直接处理预检命令,if 后要带空格
        if ($request_method = OPTIONS) {
            return 200;
        }
    }
}

Fourth, the front-end server to solve cross-domain

But in fact, in most cases, we will forward the request and the front-end applications on the same stage on Nginx

server{
    listen 80; // 监听80端口
    server_name a.com; // 监听向 a.com 发送的请求

    location / {
        root   html;
        index  index.html index.htm;
    }

    locltion /ajaxserver {
        proxy_pass http://ser432ver.53253bb.com:8080; // 后端地址
    }
}

Such is the essence of hidden cross-domain, so that the browser sees no cross-domain access to other domains will not happen.

Code needs to be coupled with the front end in front of each ajax request/ajaxserver

V. References

cross-domain ajax fully explain

https://www.imooc.com/learn/947

SpringBoot use CORS to solve the problem of cross-domain request

https://www.cnblogs.com/7788IT/p/10693073.html

Spring MVC's @RequestParam @RequestBody @RequestHeader etc. Detailed

https://blog.csdn.net/summerSunStart/article/details/78676781

You do not know the "cross-domain CORS"

https://www.jianshu.com/p/abb5f6bf92c3

A little more understanding on cross-domain issues and security

https://blog.csdn.net/jaytalent/article/details/52213576

On the cross-domain security threats

https://www.freebuf.com/articles/web/208672.html

cors cross-domain errors on access-control-allow-headers caused

https://www.jianshu.com/p/cecb73b26a11

What is cross-domain? Cross-domain solutions

https://blog.csdn.net/qq_38128179/article/details/84956552

Spring Cloud Configuration 5 designs cross-domain access? You use which is it?

https://segmentfault.com/a/1190000017188296

servlet cross-domain requests

https://blog.csdn.net/qq_34135615/article/details/82900786

Cross-domain (CORS) solutions, why Access-Control-Allow-Methods does not work?

https://segmentfault.com/q/1010000005067552/a-1020000005067822

Guess you like

Origin www.cnblogs.com/n031/p/11828797.html