跨域(CrossOrigin)
1. 介绍
1) 跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。
通俗讲,当一个请求的URL的端口、协议和域名三者之间任意一个与当前页面的URL不同即为跨域。
换句话说,跨域问题就是浏览器的一种安全策略,限制了网页在不同源(Origin)之间进行的某些操作;如:读取网页的数据,资源等。
2) 为什么会发生跨域问题:跨域问题的发生源于浏览器的同源策略(Same-Origin Policy),这是浏览器的一种安全机制(是一种约定),旨在防止恶网站户获取用户数据。同源策略要求一个网页的JavaScript脚本只能与同一个端口、协议和域名的资源进行交互,而不能访问与其来源不同的资源。
如此设计为了保护用户的隐私和安全,防止恶意网站通过脚本等方式获取用户在其它网站的数据。如果缺少同源策略,浏览器的正常功能都会受到影响。
2. 跨域解决方案
1) JSONP(JSON with Padding):JSONP时一种古旧的跨域解决方案,利用<script>标签不受同源策略的特性,通过动态创建<script>标签来获取跨域资源。
1.客户端(前端)构造一个包含了回调函数的 URL 请求,并将这个 URL 作为 <script> 标签的 src 属性值。
2.服务器端(后端)接收到这个请求后,解析其中的回调函数名,并将相应的 JSON 数据作为参数传入该回调函数。
3.客户端定义了一个全局的 JavaScript 函数,其函数名就是前面提到的回调函数名,服务器返回的 JSON 数据作为该函数的参数。
4.当浏览器加载这个包含 JSON 数据的 JavaScript 文件时,就会立即执行这个全局函数,从而完成跨域数据的获取和处理。
JSONP的缺点:
安全性问题:不受同源策略的限制,无法保证从服务器返回的数据是否安全可信;
仅支持GET请求:限制了在处理其他类型的HTTP请求;
依赖回调函数:需要在客户端命名一个全局的JavaScript函数来处理返回的数据,意味着客户端需提前约定好回调函数的名称,容易引发命名冲突和管理困难;
无法处理错误信息:JSONP请求没有像Ajax请求那样的错误处理机制,无法捕获服务器返回的HTTP状态码和错误信息,使得调试和处理错误变得困难;
总之,并不建议使用JSONP方式解决跨域问题。
2) 添加响应头(后端)
跨域资源共享(CORS):是一种跨域解决方案,通过在服务器端添加特定的响应头来允许跨域请求。
Access-Control-Allow-Origin: 指定允许访问该资源的源,可以是单个源或者是通配符 *
,表示允许所有源访问该资源。
例:在Java 控制器(Controller)方法中,使用 HttpServletResponse 对象来设置响应头信息。在 Controller 方法中设置 CORS 响应头,指定允许访问的来源(origins)。
@RestController public class CrossOriginController { @CrossOrigin(origins = "http://127.0.0.1:8080") // 只允许单个来源 @CrossOrigin(origins = {"http://moudu.com", "http://mouxun.com"}) // 允许多个来源 public String Test(HttpServletResponse httpServletResponse) { return "Hello, CORS."; } }
注意:在Spring Framework内,@CrossOrigin注解不可以在同一个方法内多次使用。可以在同一个控制层的每个方法内使用。
常用CROS响应头:
1.Access-Control-Allow-Origin: 指定允许访问该资源的源,可以是单个源或者是通配符 *,表示允许所有源访问该资源。
2.Access-Control-Allow-Methods: 指定允许的 HTTP 方法,例如 GET、POST 等。
3.Access-Control-Allow-Headers: 指定允许的 HTTP 头字段。
4.Access-Control-Allow-Credentials: 指定是否允许发送 Cookie。
5.Access-Control-Expose-Headers: 指定哪些 HTTP 头字段可以在客户端进行访问。
6.Access-Control-Max-Age: 指定预检请求的有效期,单位为秒。
3) 配置文件(后端常用)
在Spring Boot中,可以使用配置文件设置全局的跨域策略。然后让Spring Boot应用程序在每个请求中配用这些配置。
项目需要简单的全局跨域配置,并且习惯于基于配置的开发模式,配置文件方式更适合。
优点:
- 配置简单,一次配置后整个应用程序都会生效;
- 简单的全局跨域配置,适合于小型项目或不需要复杂跨域策略的应用;
application.properties 文件中配置跨域策略:
# 允许的跨域来源
cors.allowed-origins=http://127.0.0.1:8080,http://moudu.com,http://mouxun.com
# 允许的跨域方法
cors.allowed-methods=GET,POST,PUT,DELETE
# 允许的跨域头
cors.allowed-headers=Content-Type,Authorization
# 是否允许发送 Cookie
cors.allow-credentials=true
# 预检请求的有效期,单位为秒
cors.max-age=3600
@Configuration public class CorsConfig implements WebMvcConfigurer { @Value("${cors.allowed-origins}") private String allowedOrigins; @Value("${cors.allowed-methods}") private String allowedMethods; @Value("${cors.allowed-headers}") private String allowedHeaders; @Value("${cors.allow-credentials}") private boolean allowCredentials; @Value("${cors.max-age}") private long maxAge; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins(allowedOrigins.split(",")) .allowedMethods(allowedMethods.split(",")) .allowedHeaders(allowedHeaders.split(",")) .allowCredentials(allowCredentials) .maxAge(maxAge); } }
简单的Servlet过滤器,用于处理跨域资源共享(CORS)请求。config包下,可直接使用;(常用)
项目需要更灵活地控制跨域策略,甚至根据请求的具体情况动态设置跨域响应头,过滤器方式更合适。
优点:
- 更灵活,根据具体的请求情况动态,设置跨域响应头;
- 可以在过滤器中编写复杂的逻辑,对请求进行定制化处理;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component public class HttpFilter implements Filter { /** * CROS跨域常用header Access-Control-Allow-Origin: 允许哪些ip或域名可以跨域访问 Access-Control-Max-Age: 表示在多少秒之内不需要重复校验该请求的跨域访问权限 Access-Control-Allow-Methods: 表示允许跨域请求的HTTP方法,如:GET,POST,PUT,DELETE Access-Control-Allow-Headers: 表示访问请求中允许携带哪些Header信息,如:Accept、Accept-Language、Content-Language、Content-Type */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //*号表示对所有请求都允许跨域访问 HttpServletResponse res = (HttpServletResponse) response; res.addHeader("Access-Control-Allow-Credentials", "true"); res.addHeader("Access-Control-Allow-Origin", "*"); res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { response.getWriter().println("Success"); return; } chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } }
若都配置后发现依然存在跨域等问题时,根据前端提示查看:res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); 是否未添加前端需要的其他的请求头信息。
4) WebMVC全局配置(后端解决跨域最常用)
// WebMVC全局配置 @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { // 设置允许跨域的路径 registry.addMapping("/**") // 设置允许跨域请求的域名 .allowedOriginPatterns("*") // 是否允许cookie .allowCredentials(true) // 设置允许的请求方式 .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS") // 设置允许的header属性 .allowedHeaders("*") // 跨域允许时间 .maxAge(3600); } }
5) Nginx跨域
Nginx是一个高性能的反向代理服务器,也可用作Web服务器、负载均衡等。通过Nginx,可以实现跨域请求的解决方案。一般解决的是前端静态页面在不同服务器间的访问。
使用Nginx设置跨域请求头:
- 安装和配置Nginx;
- 编辑Nginx文件;
- 设置跨域设置;
location / {
# 添加以下跨域配置
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization';
# 支持 OPTIONS 请求
if ($request_method = 'OPTIONS') {
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
4. 重启 Nginx 服务: 保存并关闭配置文件后,重新加载 Nginx 配置,以使更改生效:sudo systemctl reload nginx
或
server/ {
listen 80;
server_name test01.xqiangme.to;
#允许跨域请求的域,* 代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
location /index.html {
alias /home/nginx/static_html/index_test01.html
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂