跨域问题以及解决方式

什么是跨域?

同源策略:浏览器限制网页向不同源的服务器发送请求,目的是防止一个恶意网站在用户不知情的情况下获取或篡改其他的网站的数据

协议、域名、端口号有一个不同,就是不同源,就表示跨域。

前后端跨域问题:在开发过程中,前端和后端通常运行在不同的端口上,比如:

前端:http://localhost:3000
后端:http://localhost:8080

比如在前端项目中,直接请求后端的 API(如 http://localhost:8080/api/user),浏览器会触发 跨域请求(CORS)限制。因为前端的源是http://localhost:3000,后端的源是http://localhost:8080,不满足同源策略。

ant design pro通过代理的方式实现跨域:

export default {
  dev: {
    // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
    '/api': {
     
      // 要代理的地址
      target: 'http://localhost:8080',
      // 配置了这个可以从 http 代理到 https
      // 依赖 origin 的功能可能需要这个,比如 cookie
      changeOrigin: true,
    },
      //......

上面这段代码配置的跨域实现方式确实是通过代理服务器的手段,而这个代理服务通常由 Webpack Dev Server 提供。即Webpack Dev Server 就是代理服务器。

代码解析:通过配置 /api 路径的代理规则,前端开发服务器会将 /api 开头的请求代理到 http://localhost:8080。代理服务器会拦截浏览器对 /api 的请求,替换目标地址为后端服务地址(http://localhost:8080),并将响应返回给浏览器。

为什么代理服务器能实现跨域?前端浏览器的源是http://localhost:3000,代理服务器的源也同样是http://localhost:3000,前端浏览器先将请求发送到与之同源的代理服务器,然后代理服务器将请求转发到不同源的后端服务器,但是因为代理服务器不涉及浏览器,所以不会被浏览器的同源策略所限制。其实就是通过代理服务器作为中介,避免了浏览器直接与不同源的后端通信。

跨域问题的解决方式

方法1:在nginx的配置文件中加上允许跨域的配置

# 跨域配置
location ^~ /api/ {
# ^~ 表示当前的 location 定义是一个 前缀匹配,且如果匹配成功,将 忽略其他的正则匹配规则
    proxy_pass http://127.0.0.1:8080/api/;
    # 拦截所有路径以 /api/ 开头的请求,并通过 proxy_pass 转发到后端服务 http://127.0.0.1:8080/api/。
    add_header 'Access-Control-Allow-Origin' $http_origin;
    # 指定允许哪些域名发起跨域请求。
    add_header 'Access-Control-Allow-Credentials' 'true'; # 表示服务器是否允许携带 Cookie 等身份凭证。值为 true:允许前端在跨域请求中携带 Cookie 或其他凭证。
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; #指定允许的 HTTP 方法(如 GET、POST、OPTIONS 等)。
    add_header Access-Control-Allow-Headers '*'; # 指定前端可以发送哪些自定义请求头。
    # 处理预检请求(OPTIONS)
    if ($request_method = 'OPTIONS') { # 判断请求方法是否为 OPTIONS。如果是 OPTIONS 请求,服务器将返回一个快速响应,表明支持跨域。
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Origin' $http_origin; # 允许请求的源
       add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; #允许的 HTTP 方法
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; # 允许的请求头
        add_header 'Access-Control-Max-Age' 1728000; # 表示预检请求的结果在浏览器缓存中的有效时间
        add_header 'Content-Type' 'text/plain; charset=utf-8'; 
        add_header 'Content-Length' 0;
        return 204; # 返回 HTTP 状态码 204 No Content,表示服务器接受预检请求
    }
}
# Access-Control-Allow-Origin用于指定允许哪些域名发起跨域请求。`$http_origin`表示当前发起这个跨域请求的域名。这句的意思就是说:允许发起跨域请求的这个域名进行跨域。也就是说这句配置表示:允许所有请求进行跨域。
# 什么是预检请求?
# 当浏览器发起跨域请求且请求不符合 简单请求 的标准(比如请求方法是 PUT、DELETE,或带有自定义头部时),浏览器会自动发送一个 OPTIONS 请求,询问服务器是否允许跨域请求。

修改后端服务,在后端配置跨域

方法2:在代码中添加@CrossOrigin配置,在UserController类上面添加以下代码:

@CrossOrigin(origins = "http://localhost:8000",allowCredentials = "true")
// 上面这个配置就是意思:允许localhost:8000请求跨域到后端
// localhost:8000表示的是前端项目的域名

方法3:添加web请求拦截器

package com.neu.deliveryPlatform.config;

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

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径 
        registry.addMapping("/**")  // 自己按需要修改哦
                // 设置允许跨域请求的域名
            	// 这里写的*表示允许所有域,实际情况可能有以下几种形式
            	// .allowedOrigins("http://app.example.com:80"); 写全了,个人认为最正规的写法,但是更喜欢用下面这种
            	// .allowedOrigins("http://app.example.com"); 只写了协议和域名,端口使用http默认的80,https的话是443,应该是最常用的写法(因为一般都使用默认的端口)
            	// .allowedOrigins("http://123.123.123.123:8888"); 前端服务器没有域名的情况下,也可以使用ip地址
                .allowedOriginPatterns("*")
                // 是否允许cookie
                .allowCredentials(true)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间,用于设置预检请求(OPTIONS方法)的缓存时间(单位秒)。设置为 3600(即1小时)表示浏览器可以缓存这个CORS响应信息1小时,期间对同一源的跨域请求不再发送预检请求,直接使用缓存结果,从而提高性能。
                .maxAge(3600);
    }
}

PS:这是我个人的一些理解,大家可以做个参考,有错误麻烦再评论区指出,一起加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值