文章目录
一.跨域
什么是跨域?浏览器为了用户的安全,仅允许向 同域名、同端口 的服务器发送请求。
二.CORS
CORS(Cross-Origin Resource Sharing)是跨域资源共享的缩写,是一种机制,使用额外的HTTP头来告诉浏览器允许一个网页从另一个域请求资源,从而实现服务器和客户端之间的安全跨域通信。
CORS是一种机制,用于允许跨域请求。在Web应用程序中,由于浏览器的同源策略(Same-Origin Policy),浏览器会限制从一个源(域、协议、端口)发起的HTTP请求,只能访问同一源上的资源。CORS通过在服务器端和客户端之间添加一些额外的HTTP头信息,来解决跨域问题。在Spring Boot中,我们可以使用CORS配置来设置允许跨域访问的规则。
三.如何解决跨域
3.1 nginx
3.1.1 Nginx 解决跨域原理
- 跨域问题的原因 跨域问题是由浏览器的 同源策略(Same-Origin Policy) 引起的。同源策略要求: 协议、域名、端口都必须一致。 如果前端和后端运行在不同的域名、IP 或端口上,例如: 前端地址为 http://126.4.3.3 后端地址为 http://126.4.3.3:8080 浏览器会认为它们是不同源,因此会阻止请求,这是跨域问题的本质。
- 如何解决跨域问题的配置逻辑 Nginx 配置中,location /api 是关键:
location /api {
proxy_pass http://127.0.0.1:后端端口;
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_set_header Connection "";
}
这里通过 Nginx 的反向代理机制: 将前端通过 /api 路径发起的请求转发到后端(即 http://127.0.0.1:后端端口 )。 对于前端来说,请求的域名和端口仍然是 http://126.4.3.3 ,从浏览器的角度看,请求是同源的。
3.1.2 解决跨域方式
前端
前端请求地址和前端运行地址一致 也就是前端 baseURL 请求 192.168.196.158:8000 具体参考自己运行地址。
后端
需要修改宝塔具体位置
server
{
listen 80;
server_name 前端 IP 比如 126.4.3.3;
root 前端路径;
location /api {
proxy_pass http://127.0.0.1:后端端口;
proxy_set_header Host $proxy_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_set_header Connection "";
}
# 这个要写在下面!
location / {
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
BUG
比如,下面这种情况:
所以会导致跨域失败!
解决方法:前端的 baseUrl 前端运行地址
3.2 修改后端服务
3.2.1 配置 @CrossOrigin ]注解
3.2.1.1 controller方法的CORS配置
你可以向@RequestMapping注解处理程序方法添加一个@CrossOrigin注解,以便启用CORS(默认情况下,@CrossOrigin允许在@RequestMapping注解中指定的所有源和HTTP方法):
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
其中@CrossOrigin中的2个参数:
- origins: 允许可访问的域列表
- maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
3.2.1.2 为整个controller启用@CrossOrigin
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
在这个例子中,对于retrieve()和remove()处理方法都启用了跨域支持,还可以看到如何使用@CrossOrigin属性定制CORS配置。
3.1.2.3 同时使用controller和方法级别的CORS配置
Spring将合并两个注释属性以创建合并的CORS配置。
3.2.2 全局CORS配置
@Configuration
public class WebMvcConfg implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//设置允许跨域的路径
registry.addMapping("/**")
//设置允许跨域请求的域名
//当**Credentials为true时,**Origin不能为星号,需为具体的ip地址【如果接口不带cookie,ip无需设成具体ip】
.allowedOrigins("http://localhost:9527", "http://127.0.0.1:9527", "http://127.0.0.1:8082", "http://127.0.0.1:8083")
//是否允许证书 不再默认开启
.allowCredentials(true)
//设置允许的方法
.allowedMethods("*")
//跨域允许时间
.maxAge(3600);
}
}
模版
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
上述代码中,我们创建了一个名为CorsConfig
的配置类,并实现了WebMvcConfigurer
接口。在addCorsMappings
方法中,我们使用CorsRegistry
对象配置了CORS允许的规则。具体而言,我们允许所有的来源(allowedOrigins("*")
)、所有的HTTP方法(allowedMethods("*")
)、所有的请求头(allowedHeaders("*")
)、允许携带身份凭证(allowCredentials(true)
)并设置了缓存时间(maxAge(3600)
)。
四. 注意
- 直接请求后端端口,那么 Nginx 就失去了反向代理的意义。
- 后端配置文件如果写了 samesite 或者 sercure 属性要删除掉!
- 后端写了跨域配置要 删除/注释 一般是 @CrossOrigin 或者 CrosConfig
- 前端使用域名,但是前端后端使用 ip ,导致 session 设置不上。
解决:前后端统一,要用域名都用域名、IP 都用 IP。
- 用 Nginx 跨域就不需要用 Nginx 跨域就不需要,跨域方式不能共存。
- 我们现在无法通过浏览器访问接口文档:http://81.69.229.63:8123/api/doc.html。这是因为我们的服务器防火墙没有放开 8123 端口。这里我们故意不放开,因为在之前的部署规划中,后端需要通过 Nginx 进行转发,从而解决跨域问题。
五.小结
几种后端解决跨域的方法:
1)设置 CORS 响应头:后端可以在 HTTP 响应头中添加相关的 CORS 标头,允许特定的源(域名、协议、端口)访问资源。Spring Boot 项目中,可以通过配置 CorsFilter Bean 或者 Web 拦截器(实现 WebMvcConfigurer 接口)实现,不依赖第三方服务。
2)使用代理服务器:可以使用 Nginx 反向代理,通过 add_header 给后端响应添加 Access-Control-Allow-Origin 头,不改代码实现跨域。
3)@CrossOrigin 注解:Spring Boot 项目可以直接在对应的 Controller 或接口方法上添加 @CrossOrigin 注解实现跨域,但这种方式对代码的侵入性较大。
onfigurer 接口)实现,不依赖第三方服务。
2)使用代理服务器:可以使用 Nginx 反向代理,通过 add_header 给后端响应添加 Access-Control-Allow-Origin 头,不改代码实现跨域。
3)@CrossOrigin 注解:Spring Boot 项目可以直接在对应的 Controller 或接口方法上添加 @CrossOrigin 注解实现跨域,但这种方式对代码的侵入性较大。
2)使用代理服务器,不需要考虑特定的后端接口实现代码,是一种更通用的解决跨域的方法。
标签:http,CrossOrigin,最全,全网,Nginx,proxy,CORS,跨域 From: https://blog.csdn.net/weixin_69912448/article/details/145269787