解决xxx by CORS policy: No ‘Access-Control-Allow-Origin‘ header is present on the requested resource问题

Problem recurrence

When I logged in to ant design pro today, a login failure problem was reported, so I opened the console, as shown in the following figure:

insert image description here

The error message isAccess to XMLHttpRequest at 'http://127.0.0.1:8088/user/login' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

translated into Chinese is从源“http://127.0.0.1:8000”访问“http://127.0.0.1:8088/user/login”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查 :请求的资源上不存在“Access-Control-Allow-Origin”标头。

This problem is simply a cross-domain problem, but why is there a cross-domain problem?

cross domain phenomenon

Reasons for cross-domain error reporting: The request is cross-domain, and an error may not necessarily be reported. Ordinary image requests, css file requests will not report errors

Conditions for errors in cross-domain requests: browser 同源策略&& request is of type ajax

what is cross domain

It means that the browser cannot execute the scripts of other websites. It is 同源策略caused by the browser, which is the security restriction imposed by the browser on javascript.

For example, in order to obtain a resource under domain name B from a page under domain name A (general ajax or CORS requests, etc.), but the browser's 同源策略restrictions do not allow such things to happen by default, so cross-domain is required.

Why cross-domain

In some cases, we need cross-domain access. For example, programmers developing websites may need to access server data locally. Another example is that a company's page A ( a.superjson.com) may need to obtain page B ( b.superjson.com).

Same Origin Policy

What is the Same Origin Policy

The same-origin policy was mentioned above, so what is the same-origin policy?

The same origin policy (Same origin policy) is a convention, which is the core and most basic security function of the browser. If the same origin policy is missing, the normal functions of the browser may be affected. The same-origin policy is a key security mechanism that restricts how documents or scripts loaded from one origin can interact with resources from another origin.

The requirements of the same-origin policy 协议(protocol)、域名(host)、端口号(port)must be the same, and any difference will result in cross-domain. For example, http://www.superjson.com:8000/the protocol in is http, the main domain name is superjson, the subdomain name is www, and the port number is 8000.

Take URL1 and URL2 as an example to illustrate whether they are of the same origin:

URL1 URL2 illustrate Is it homologous
http://www.superjson.com/a.js http://www.superjson.com/123/b.js The protocol, domain name, and port are all the same Homologous
http://www.superjson.com/a.js https://www.superjson.com/b.js The protocol is different, the domain name and port are the same non-homologous
http://www.superjson.com/a.js http://superjson.com/b.js Different domain names, same protocol and port non-homologous
http://www.superjson.com:80/a.js http://www.superjson.com:8080/b.js The port is different, the domain name and protocol are the same non-homologous

Why the same-origin policy exists

If you have just entered your account password in online banking, checked that you still have 10,000 yuan, and then visit some unruly websites. This website can access the online banking site just now and obtain the account password, then the consequences can be imagined.

Therefore, from a security point of view, the same-origin policy is conducive to protecting website information.

Solve cross-domain problems

My backend uses spring boota framework, so I can configure the following code:

package com.superjson.superjsonmanager.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import static com.superjson.superjsonmanager.constants.CorsConfigConstant.*;

/**
 * @author 念兮为美
 * @datetime 2022/8/5 22:32
 * @desc 解决跨域的过滤器
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    
    
    // 添加映射路径
    registry
        .addMapping(ADD_MAPPING)
        // 是否发送Cookie
        .allowCredentials(ALLOW_CREDENTIALS)
        // 设置放行哪些原始域   SpringBoot2.4.4下低版本使用.allowedOrigins("*")
        .allowedOriginPatterns(ALLOWED_ORIGIN_PATTERNS)
        // 放行哪些请求方式
        .allowedMethods(
            new String[] {
    
    
              ALLOWED_METHODS_GET, ALLOWED_METHODS_POST, ALLOWED_METHODS_PUT, ALLOWED_METHODS_DELETE
            })
        // 或者放行全部
        .allowedMethods(ALLOW_ALL)
        // 放行哪些原始请求头部信息
        .allowedHeaders(ALLOW_ALL)
        // 暴露哪些原始请求头部信息
        .exposedHeaders(ALLOW_ALL);
  }
}
package com.superjson.superjsonmanager.constants;

/**
 * @author 念兮为美
 * @datetime 2022/8/9 09:13
 * @desc 设置解决跨域问题的常量
 */
public class CorsConfigConstant {
    
    

  public static final String ADD_MAPPING = "/**";

  public static final boolean ALLOW_CREDENTIALS = true;

  /**
   * 配置允许访问的域名
   *
   * <ul>
   *   <li>https://*.domain1.com -- 以domain1.com域名结尾
   *   <li>https://*.domain1.com:[8080,8081] -- 以domain1.com结尾的端口号为8080或8081
   *   <li>https://*.domain1.com:[*] -- 以domain1.com结尾的任意端口号
   * </ul>
   */
  public static final String ALLOWED_ORIGIN_PATTERNS = "http://127.0.0.1:[8000,1234]";

  public static final String ALLOWED_METHODS_GET = "GET";

  public static final String ALLOWED_METHODS_POST = "POST";

  public static final String ALLOWED_METHODS_PUT = "PUT";

  public static final String ALLOWED_METHODS_DELETE = "DELETE";

  public static final String ALLOW_ALL = "*";
}

Other solutions to cross-domain problems

JSONP

The principle is: some tags script、img、link、iframe ... do not have restrictions on cross-domain requests, and this feature is used to solve cross-domain problems.

JSONP is a common method for cross-origin communication between servers and clients:

  • Advantages: simple and applicable, good compatibility (compatible with lower versions of IE),
  • Disadvantages: only supports get requests, not post requests, resulting in data insecurity

<script>The core idea: the web page requests JSONdata from the server by adding an element, and after the server receives the request, it puts the data in the parameter position of a callback function with a specified name and sends it back.

  1. Native implementation (JSONP requires support from the server)
<script src='http://www.superjson.com/data?callback=func'></script>
<!-- 向服务器 www.superjson.com 发出请求,该请求的查询字符串有一个 callback 参数,用来指定回调函数的名字 -->
<!-- 给客户端返回数据 "func('+JSON.stringify(data)+')" ,浏览器把字符串变成 js 表达式执行 -->

<!-- func 需要是一个全局函数 -->
<script type='text/javascript'>
  function func(res){
    
    
    // 处理获得的数据
  }
  
</script>
  1. The JSONP processing method provided by jQuery
$.ajax({
    
    
  url: 'http:/www.superjson.com:8000/login',
  type: 'get',
  dataType: 'jsonp',// 设置请求方式为 jsonp
  jsonpCallback: 'handleCallback',// 自定义回调函数名 
  data: {
    
    }
})
  1. Vue.js
this.$http.jsonp('http://www.superjson.com:8080/login', {
    
    
  	params: {
    
    },
    jsonp: 'handleCallback'
  }).then(res => {
    
    
  //
});

CORS cross domain resource sharing

CORS Cross-Origin Resource Sharing, ie Cross-Origin Resource Sharing. Its new set of HTTP header fields allows the server to declare which resources those source requests have access to, that is, it allows the browser to make cross-domain requests to the stack that declares CORS.

Access-Control-Allow-OriginThe main feature of this method is that information such as will be added to the HTTP header of the response to determine which resource sites can make cross-domain requests, and there are several other related HTTP headers for more fine-grained control, the most important thing is Access-Control-Allow-Origin.

The comparison between CORS and JSONP is more obvious. JSONP only supports the GET method, and JSONP does not conform to the normal process of processing business. Using CORS, the front-end encoding is no different from normal non-cross-origin requests.

  1. The client sends a request (ajax):

Before the real cross-domain request is sent, a tentative request (OPTIONS) will be sent. After the server receives the OPTIONS request, it will do a process and return success, indicating that the cross-domain request can be sent, and then the real cross-domain request can be sent.

The server sets related header information (need to process tentative request OPTIONS)

  1. Cross-domain requests with cookies: Both the front and back ends need to be set

front end settings

xhr.withCredentialsJudging whether there is a cookie according to the field

  • native ajax
var xhr = new XMLHttpRequest();// ie8/9 需用 window.XDomainRequest 兼容

// 前端设置是否带 cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.superjson.com:8000/index', true);
xhr.setRequestHeader('Content-ype', 'application/x-www-form-urlencoded');
xhr.send('user=admin');

xhr.onreadystatechange = function() {
    
    
  if (xhr.readyState == 4 && xhr.status == 200) {
    
    
    alert(xhr.responseText)
  }
};
  • native ajax
$.ajax({
    
    
  url: 'http://www.superjson.com:8000/index',
  type: 'get',
  data: {
    
    },
  xhrFields: {
    
    
    withCredentials: true// 设置前端是否带 cookie
  },
  crossDomain: true// 会让请求头中包含跨域的额外信息,但不会含 cookie
});

  • vue-resource
Vue.http.options.credentials = true
  • axios
axios.defaults.withCredentials = true

server settings

The server supports CORS mainly through settings Access-Control-Allow-Origin. Ajax can be allowed for cross-domain access if the browser detects the appropriate setting:

// 不使用*,自动适配跨域域名,避免携带Cookie时失效
String origin = request.getHeader('Origin');
if (StringUtils.isNotBlank(origin)) {
    
    
  response.setHeader('Access-Control-Allow-Origin', origin);

}
// 自适应所有自定义头
String headers = request.getHeader('Access-Control-Request-Headers');
if (StringUtils.isNotBlank(headers)) {
    
    
  response.setHeader('Access-Control-Allow-Headers', headers);
  response.setHeader('Access-Control-Expose-Headers', headers);
}

// 允许跨域的请求方法类型
response.setHeader('Access-Control-Allow-Methods', '*');
// 预检命令(OPTIONS)缓存时间,单位:秒
response.setHeader('Access-Control-Max-Age', '3600');
// 明确许可客户端发送Cookie,不允许删除字段即可
response.setHeader('Access-Control-Allow-Credentials', 'true');

reverse proxy

Since cross-domain requests are not possible, we can do without cross-domain. By deploying a service before the request reaches the server, the interface request is forwarded. This is the reverse proxy. Front-end requests can be forwarded to other services through certain forwarding rules.

Through the reverse proxy, we unify the front-end and back-end projects through the reverse proxy to provide external services, so that the front-end looks like there is no cross-domain.

The troublesome part of the reverse proxy lies in Nginxthe configuration of the original peer-to-peer reverse proxy service. This method is used in many projects where the front and back ends are currently separated.

proxyTable: {
    
    
   '/api': {
    
    
     target:'http://api.douban.com/v2', // 你请求的第三方接口
     changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
     pathRewrite:{
    
      // 路径重写,
       '^/api': ''  // 替换target中的请求地址,也就是说以后你在请求http://api.douban.com/v2/XXXXX这个地址的时候直接写成/api即可。
     }
   }
 },

reference documents

  1. http://www.manongjc.com/detail/29-cpaozffgzyhvbjc.html

Guess you like

Origin blog.csdn.net/lvoelife/article/details/126244103