跨域问题及常用的5种解决方案

1**.什么是跨域问题?**

跨域问题通常指的是在浏览器中由于同源策略的限制而产生的问题。同源策略(Same-origin policy)是浏览器的一种安全措施,它要求请求的域名、协议和端口必须与提供资源的网站相同。当一个网页尝试访问另一个来源(即不同域名、协议或端口)的数据时,那么后端返回给浏览器的数据被浏览器拦截下来,这就是跨域。

2.跨域问题演示?

在这里,不同的端口号意味着不同的"来源"(origin),因此即使它们都在 localhost 上运行,也会被视为来自不同的源。浏览器的同源策略会阻止从一个源发起的请求访问另一个源上的资源。

3.什么是同源策略?

同源策略(Same-origin policy)是浏览器的一项重要安全特性,用于控制不同来源的网页之间的交互。这项政策的主要目的是为了保护用户的隐私和数据安全,防止恶意网站执行某些恶意操作。

但在实际应用中,有些情况下需要跨域访问。以下是一些常用的跨域访问机制:

4..跨域问题的原因分析?

一般来讲,源由协议、域名和端口号组成。如果两个 URL 的协议、域名和端口号中任何一个不同,就被认为是跨域。通常产生跨域问题有以下几种原因:

  1. 协议不同:如 https和http;

  2. 端口不同

  3. 域名不同

这就是常说的同源策略的问题。产生跨域问题的根源就是请求不同源。

5.如何解决跨域问题?

我们在项目中解决跨域问题主要是通过Cors 机制,用于在Web浏览器中实现跨源资源共享。这是目前比较常用的方式,它的原理是通过在响应头中添加一些额外的字段,如 Access-Control-Allow-Origin 字段,添加允许跨域的源,类似于设置白名单之类的操作。

一、使用@CrossOrigin注解

  @CrossOrigin(origins="*", allowedHeaders = "*"methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE,RequestMethod.OPTIONS})

GraphQL

也可以在这个注解里添加允许的请求方法,就像上边这句代码一样

allowedHeaders = "*" 这段配置通常用于后端服务中,以确保客户端可以从不同的源发起请求,并且可以使用特定的HTTP头部。

OPTIONS方法: 用于预检请求,检查服务器是否允许特定的跨域请求。

了解预检请求:

CORS机制中的预检请求(Preflight Request)是浏览器为了确保跨域请求的安全性和兼容性而自动发送的一种特殊类型的HTTP请求。预检请求主要用于检查服务器是否允许特定类型的跨域请求。

预检请求的工作原理

  1. 客户端发送预检请求

  2. 浏览器发送一个 OPTIONS 方法的请求到目标服务器。

  3. 请求头中包含 Access-Control-Request-Method,指明客户端打算使用的HTTP方法。

  4. 请求头中包含 Access-Control-Request-Headers,列出客户端打算使用的自定义头部。

  5. 服务器响应预检请求

  6. 服务器应该返回一个200状态码的响应,表明请求被接受。

  7. 响应头中包含 Access-Control-Allow-Origin,指明允许的源。

  8. 响应头中包含 Access-Control-Allow-Methods,指明允许的HTTP方法。

  9. 响应头中包含 Access-Control-Allow-Headers,指明允许的自定义头部。

  10. 响应头中可包含 Access-Control-Max-Age,指明预检请求的有效期(秒)。

  11. 客户端发起实际请求

  12. 如果预检请求成功,浏览器会根据服务器的响应发送实际的跨域请求。

  13. 如果预检请求失败,浏览器将阻止实际请求的发送。

OPTIONS请求方法的主要用途有两个:

1、获取服务器支持的HTTP请求方法;也是黑客经常使用的方法。

2、用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

二、使用全局跨域配置

三. 使用CorsFilter跨域

四.Node代理 ?

Node代理 是指用 Node 服务器代理客户端和目标服务器之间的网络请求。同源策略是浏览器需要遵循的标准,服务器与服务器之间没有同源策略,Node 代理服务器监听客户端请求,转发给目标服务器,再接收响应发给客户端。

只需在 vite.config.js 文件中配置开发服务器的自定义代理规则:

  server: {


      proxy: {
            '/api': {
              target: 'http://localhost:8080',
              changeOrigin: true,

            }
          }
      
       },

GraphQL

五.使用Nginx来实现跨域

location /api {            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'POST,GET,OPTIONS';             //OPTIONS方法通常用于预检请求(Preflight Requests),这是一种特殊的请求,用于检查服务器是否支持跨域请求及其相关参数。}

GraphQL

这里是我们在wms项目里打包部署服务器时的前端项目里配置Nginx的一个文件,

upstream wms-app {    server 192.168.21.92:8080; server 192.168.21.92:8081;
}server {    listen       80;    listen  [::]:80;    server_name  localhost;
    access_log  /var/log/nginx/host.access.log  main;
    location / {        root   /usr/share/nginx/html;        index  index.html index.htm;        try_files $uri $uri/ /index.html; #解决单页面找不到路径问题 404    }       location /api {            add_header 'Access-Control-Allow-Origin' '*';            add_header 'Access-Control-Allow-Methods' 'POST,GET,OPTIONS';            proxy_pass http://wms-app ;  #可以配置多个下游服务,具有负载功能            #proxy_pass http://192.168.14.3:3666; #仅配置一个下游服务,不具有负载均衡能力
    }    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /usr/share/nginx/html;    }

}

GraphQL

在讲完跨域后再扩展一下Nginx的配置吧

5.1 proxy_pass http:

当你需要将请求分发到多个后端服务器时,需要实现负载均衡功能,可以使用upstream指令定义一组服务器,并在proxy_pass中引用这个服务组名称。。如果不需要负载均衡,只需要将请求转发到单一的后端服务器,可以直接在proxy_pass指令中指定服务器地址。

5.2 proxy_set_header:

proxy_set_header是Nginx中的一个指令,用于在代理请求时设置或修改HTTP请求头。当你使用Nginx作为反向代理时,这个指令非常有用,因为它可以帮助你传递必要的信息给后端服务器。

设置Host头部:

proxy_set_header Host $host;

Plain Text

  • 由于Nginx可能监听多个不同的域名或端口,因此需要告诉后端服务器原始请求的目标主机名,当客户端向Nginx发送请求时,Nginx会自动填充$host变量的值

设置X-Real-IP头部:

proxy_set_header X-Real-IP $remote_addr;

Plain Text

为了确保后端服务器能够知道客户端的真实IP地址,而不是Nginx服务器的IP地址。

设置X-Forwarded-For头部:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Plain Text

这个头部用于记录客户端的IP地址及任何中间代理服务器的IP地址,这对于审计和跟踪请求非常有用

自定义其他头部:

通过 X-Custom-Header,你还可以设置自定义的头部信息;./'i

proxy_set_header X-Custom-Header "Some Value";i

Plain Text

5.3 Nginx作为服务端负载均衡器,常见的负载均衡算法

1. 轮询(Round Robin)

优点:

  • 简单易实现。

  • 适用于后端服务器性能相近的情况。

缺点:

  • 无法考虑服务器的负载情况。

  • 不适用于后端服务器性能差异较大的情况。

2..最少连接数(Least Connections)

最少连接数算法将请求分配给当前活动连接数最少的后端服务器。这有助于避免某些服务器过载,而其他服务器则处于空闲状态的情况。

3. IP哈希(IP Hash)

IP哈希算法根据客户端IP地址的哈希值将请求分配给后端服务器。这样,同一个客户端的请求总是被分配到同一台后端服务器,从而实现会话粘性(Session Persistence)。

优点:

  • 适用于需要会话粘性的场景。比如购物车应用或需要登录的应用程序。

  • 缓存一致性:如果后端服务器使用本地缓存来加速响应时间,那么使用 IP 哈希算法可以确保来自同一 IP 的请求始终命中相同的缓存实例,从而提高缓存的效率和命中率。

  • 减少后端服务器间的负载转移:在一些情况下,如果某个后端服务器正在进行数据库操作或其他需要较长时间的任务,将请求继续路由到该服务器可以避免在任务完成之前将请求转移到另一台服务器,从而减少不必要的负载转移。

缺点:

  • 负载分布不均衡,可能导致部分服务器负载过高。

4. URL哈希(URL Hash)

URL哈希算法根据请求URL的哈希值将请求分配给后端服务器。这样,相同URL的请求总是被分配到同一台后端服务器。

优点:

  • 适用于缓存场景,提高缓存命中率。

  • 简单实现URL粘性。

  • 静态内容优化:

对于静态内容如图片、CSS 和 JavaScript 文件,URL 哈希算法可以确保这些文件的请求始终被路由到相同的服务器,从而可以利用这些服务器上的缓存来提高加载速度。

缺点:

  • 负载分布不均衡,可能导致部分服务器负载过高。

5. 加权轮询(Weighted Round Robin)

加权轮询算法在轮询的基础上,为每台后端服务器分配一个权重。数字越大,权重越高,分配到的请求越多。适用于后端服务器性能差异较大的情况。

优点:

  • 考虑了服务器性能差异。

  • 灵活分配请求。

缺点:

  • 需要手动配置权重。
相关推荐
开心工作室_kaic1 小时前
ssm010基于ssm的新能源汽车在线租赁管理系统(论文+源码)_kaic
java·前端·spring boot·后端·汽车
代码吐槽菌1 小时前
基于SSM的汽车客运站管理系统【附源码】
java·开发语言·数据库·spring boot·后端·汽车
zdkdchao1 小时前
jdk,openjdk,oraclejdk
java·开发语言
精致先生2 小时前
问题记录01
java·数据库·mybatis
小魏冬琅2 小时前
探索面向对象的高级特性与设计模式(2/5)
java·开发语言
TT哇3 小时前
【Java】数组的定义与使用
java·开发语言·笔记
look_outs3 小时前
JavaSE笔记2】面向对象
java·开发语言
武子康3 小时前
大数据-191 Elasticsearch - ES 集群模式 配置启动 规划调优
java·大数据·elk·elasticsearch·搜索引擎·全文检索
A_aspectJ3 小时前
‌Spring MVC的主要组件有哪些?
java·spring·mvc
塔塔开!.3 小时前
Maven的依赖
java·maven