后端跨域快速入门:什么是跨域,后端如何处理跨域

本文详细解释了跨域的概念、浏览器的处理流程,以及在SpringBoot中如何通过全局配置类WebMvcConfigurer和局部@CrossOrigin注解实现CORS跨域请求的处理,包括`addCorsMappings`方法和`@CrossOrigin`的使用示例。
摘要由CSDN通过智能技术生成

跨域配置

跨域的特点:

首先要明确跨域的一些特点(有的叫域,有的叫源,我不纠结叫法,能理解跨域就行):

  • 跨域是指一个域去请求另一个域的接口
  • 域指的是 域名+协议+端口 三者,有一个不一样,就算作是不同的域
  • 跨域是浏览器的策略,也就是说没有配置跨域的情况下,使用浏览器前端页面请求接口会被浏览器拦截,使用apifox等工具则能够正常请求
  • 当用户使用前端页面调用后端接口时,原域是前端页面所在的服务器的域名+协议+端口(而不是用户的,用户一般也没有),目标域指的是后端api服务器的域名+协议+端口

跨域的流程:

浏览器再跨域请求时执行的操作:

  1. 发起请求: 用户在浏览器中访问的前端页面(源)中的JavaScript代码通过XMLHttpRequestfetch API或其他方式尝试向不同域(目标服务器)发起HTTP请求。
  2. 同源检查: 浏览器首先检查请求的源(当前页面URL)与目标URL是否同源。同源检查包括比较两者之间的协议(HTTP/HTTPS)、域名(完全匹配或子域名匹配)和端口(完全一致)。如果源与目标URL完全相同,即同源,则直接执行下一步;否则,认为这是一个跨域请求,进入跨域处理流程。
  3. 预检请求(OPTIONS): 对于非简单请求(如使用了自定义头部、PUT/DELETE等非简单方法的请求),浏览器会先发送一个预检(preflight)请求,方法为OPTIONS,询问目标服务器是否允许该跨域请求。预检请求的头部包括:
    • Origin: 发起请求的源(即当前页面URL的源)
    • Access-Control-Request-Method: 预期的HTTP方法(如POSTPUT等)
    • Access-Control-Request-Headers: 预期发送的自定义头部(如AuthorizationX-Custom-Header等)
  4. 服务器响应预检请求: 目标服务器接收到预检请求后,根据其CORS配置决定是否允许该跨域请求。如果允许,服务器在响应中返回以下CORS相关头部:
    • Access-Control-Allow-Origin: 允许的源(可以是单个源、多个源或通配符*,表示允许所有源)
    • Access-Control-Allow-Methods: 允许的方法(如GETPOSTPUTDELETE等)
    • Access-Control-Allow-Headers: 允许的自定义头部
    • Access-Control-Max-Age: 预检请求结果的缓存时间(单位秒)
    • 可选的:Access-Control-Allow-Credentials(是否允许携带凭据,如Cookie)、Access-Control-Expose-Headers(允许浏览器访问的响应头部)
  5. 预检请求通过: 浏览器收到预检请求的响应后,检查服务器返回的CORS相关头部是否允许此次跨域请求。如果允许,浏览器缓存预检结果(根据Access-Control-Max-Age),然后执行实际的跨域请求。
  6. 实际请求与响应: 浏览器向目标服务器发送实际的跨域请求。服务器处理请求并返回响应,响应中可能包含以下CORS相关头部:
    • Access-Control-Allow-Origin: 允许的源
    • 可选的:Access-Control-Allow-CredentialsAccess-Control-Expose-Headers
  7. 浏览器处理响应: 浏览器检查响应中的CORS相关头部,确认是否允许访问响应内容。如果一切符合CORS规则,浏览器将响应数据提供给前端JavaScript代码使用;否则,浏览器阻止JavaScript访问响应数据,并可能抛出错误。

注:如果是简单请求,例如GET请求POST请求且不携带自定义头部,则不发起OPTIONS请求,直接发送原本的请求

后端处理跨域请求:

后端一般有两种方式处理跨域请求,一种是全局的,一种可以精确到controller和接口

全局跨域配置:

在SpringBoot中实现WebMvcConfigurer类的addCorsMappings方法,并在该方法中设置跨域配置

该方法就会处理前端发送来的OPTIONS请求,并且返回给前端是否允许跨域的响应

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);
    }
}

局部跨域配置:

在SpringBoot中使用@CrossOrigin注解可以实现局部跨域配置

可以在controller类上使用,也可以在接口方法上使用(注意同时使用时接口的不会覆盖controller的,而是会叠加起来)

使用该配置的优先级高于全局跨域配置(实现WebMvcConfigurer类的addCorsMappings方法)

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;

@RestController
@CrossOrigin(origins = "http://frontend.example.com", methods = "*", maxAge = 3600)
public class MyController {

    @GetMapping("/api/public-data")
    @CrossOrigin(origins = "*", allowedHeaders = "*", exposedHeaders = "Custom-Header")
    public ResponseEntity<?> getPublicData() {
        // ...
    }

    // 其他控制器方法...
}
  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值