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); } }
4) 过滤器
简单的Servlet过滤器,用于处理跨域资源共享(CORS)请求。
项目需要更灵活地控制跨域策略,甚至根据请求的具体情况动态设置跨域响应头,过滤器方式更合适。
优点:
- 更灵活,根据具体的请求情况动态,设置跨域响应头;
- 可以在过滤器中编写复杂的逻辑,对请求进行定制化处理;
@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() { } }
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 } }
标签:Control,跨域,Access,Allow,允许,请求 From: https://www.cnblogs.com/warmNest-llb/p/18029911