# 解决跨域请求问题

## 背景

**浏览器的同源策略与跨域** 两个页面地址中的协议、域名和端口号一致，则表示同源。

同源策略的限制：

* 存储在浏览器中的数据，如localStroage、Cooke和IndexedDB不能通过脚本跨域访问
* 不能通过脚本操作不同域下的DOM
* 不能通过ajax请求不同域的数据

**何为ajax请求** AJAX只是一种技术，不是某种具体的东西。不同的浏览器有自己实现AJAX的组件。 AJAX 是一种在无需重新加载整个网页的情况下，能够更新部分网页的技术。 用了AJAX之后，你点击，然后页面上的一行字就变化了，页面本身不用刷。

## 无关Cookie跨域Ajax请求

服务器端通过在响应的 header 中设置 Access-Control-Allow-Origin 及相关一系列参数，提供跨域访问的允许策略。

\`\`\`java 示例 //允许所有 response.setHeader("Access-Control-Allow-Origin", "\*"); //允许特定 if(request.getHeader("Origin").contains("mydomain.com")) { response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); }

````
### spring boot 通过配置文件实现

```java
/**
* 跨域请求配置
* 可以单独作为一个配置文件类，也可以直接放在spring boot的启动类中
*/
@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        //允许跨域携带cookie
        corsConfiguration.setAllowCredentials(true);
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }
}
````

## 带Cookie的跨域Ajax请求

如果这些GET或POST请求不需要传递Cookie数据的话，就没什么问题了，但如果需要，那么会发现 虽然已经处理了跨域请求的问题，但后台始终无法获取到Cookie。跨域传输Cookie是需要后台和前台同时做相关处理才能解决的。

**前端代码** angularjs配置方法

\`\`\`javascript angularjs //单独配置 $http.post("<http://a.domain.com/Api/Product>", { productId: 3 }, { withCredentials: true, params: { name: "Ray" } }).success(function (data) { //TODO }); //全局配置 angular.module("app").config(function ($httpProvider) { $httpProvider.defaults.withCredentials = true; })

````
jquery配置方法

```javascript jquery
$.ajax({
    type: "POST",
    url: "http://a.domain.com/Api/Product",
    xhrFields: {
        withCredentials: true
    },
    success: function (data) {
        console.log(data)
    },
    error: function (data) {
        console.error(data)
    }
})
````

**后端代码** 对应客户端的 `xhrFields.withCredentials: true` 参数，服务器端通过在响应 header 中设置 `Access-Control-Allow-Credentials = true` 来运行客户端携带证书式访问。通过对 Credentials 参数的设置，就可以保持跨域 Ajax 时的 Cookie。这里需要注意的是：

服务器端 `Access-Control-Allow-Credentials = true`时，参数`Access-Control-Allow-Origin` 的值不能为 '\*'

```java
/**
* Spring Controller中的方法：
*/
    @RequestMapping(value = "/corsrequest")
    @ResponseBody
    public Map<String, Object> getUserBaseInfo(HttpServletResponse response) {
        if(request.getHeader("Origin").contains("woego.cn")) {
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        }
        response.setHeader("Access-Control-Allow-Credentials", "true");
        ...
}
```

另一种方式，在一个没有response参数的全局代码中：

```java
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
        .getRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder
        .getRequestAttributes()).getResponse();
//改写允许访问的域名地址为真实地址，解决跨域请求携带cookie问题
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
```

## 参考资料

[Angularjs之如何在跨域请求中传输Cookie](https://blog.csdn.net/mygrilzhuyulin/article/details/52690129) [跨域Ajax请求时是否带Cookie的设置](https://blog.csdn.net/wzl002/article/details/51441704)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.rizon.top/qian-duan/kua-yu-qing-qiu-wen-ti.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
