“什么是跨域?”
跨域 (Cross-Origin) 是指在浏览器的同源策略(Same-Origin Policy)下,一个网页的源(指协议、域名、端口号的组合)与另一个网页的源不同。因此,不同源的网页之间受到限制,无法直接进行通信。
同源策略(Same-Origin Policy)是一种由浏览器实施的安全机制,旨在限制一个源(指协议、域名、端口号的组合)的网页在脚本中如何与另一个不同源的资源进行交互。该策略的主要目的是防止潜在的恶意网站通过脚本访问用户的敏感信息,增强浏览器的安全性。
具体而言,同源策略限制了通过脚本访问不同源的文档、Cookie、LocalStorage 等资源。当一个网页尝试在脚本中请求另一个不同域的资源时,浏览器会阻止这个请求,以保护用户的隐私和防范潜在的安全威胁。
如何解决:
1.Spring Boot中解决跨域问题有三种主要办法
(1)注解,使用@CrossOrigin注解: 在控制器类或方法上使用@CrossOrigin注解,指定允许的域名、请求方法等。这是一种简单直接的方式
/**
* 在控制器方法或类上使用 @CrossOrigin 注解,指定允许跨域的配置。
*
* @param origins 允许访问的域名,可以使用通配符 "*" 表示允许所有域名访问。
* @param maxAge 预检请求的缓存时间,单位为秒。在此时间范围内,浏览器无需再次发起预检请求。
*/
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600)
public class MyController {
// 控制器方法
}
origins: 指定允许访问的域名。可以是一个具体的域名,也可以使用通配符 "*" 表示允许所有域名访问。在示例中,只允许来自 http://localhost:8080 的域名发起跨域请求。
maxAge: 预检请求的缓存时间,单位为秒。预检请求是一种 CORS 机制中的预检查步骤,用于确认实际请求是否安全。maxAge 指定了浏览器可以缓存预检请求的时间,即在这个时间范围内,浏览器无需再次发起预检请求。在示例中,设置为 3600 秒(1 小时)。
(2)配置全局跨域规则: 创建一个配置类,继承WebMvcConfigurerAdapter,重写addCorsMappings方法,配置全局的跨域设置
public class CorsConfig extends WebMvcConfigurerAdapter {
/**
* 重写 addCorsMappings 方法,配置全局的跨域设置。
* @param registry CorsRegistry 对象,用于配置跨域规则。
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 针对路径 "/api/**" 配置跨域规则
registry.addMapping("/api/**")
// 允许访问的域名,可以使用通配符 "*" 表示允许所有域名访问
.allowedOrigins("http://localhost:8080")
// 允许的请求方法,如 GET、POST、PUT、DELETE
.allowedMethods("GET", "POST", "PUT", "DELETE")
// 是否允许携带凭证信息(如 Cookie)
.allowCredentials(true)
// 预检请求的缓存时间,单位为秒。在此时间范围内,浏览器无需再次发起预检请求
.maxAge(3600);
}
}
(3)使用Filter进行跨域设置: 创建一个CorsFilter过滤器,配置跨域规则,然后在WebApplication中注册这个过滤器。
```c
/**
* 自定义 CorsFilter 类,继承自 OncePerRequestFilter,用于配置跨域过滤器。
*/
@Component
public class CorsFilter extends OncePerRequestFilter {
/**
* 重写 doFilterInternal 方法,处理跨域配置逻辑。
* @param request HttpServletRequest 对象,表示 HTTP 请求。
* @param response HttpServletResponse 对象,表示 HTTP 响应。
* @param filterChain FilterChain 对象,表示过滤器链。
* @throws ServletException 如果发生 Servlet 异常。
* @throws IOException 如果发生 I/O 异常。
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 设置允许访问的域名为 "http://localhost:8080"
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
// 允许的请求方法,如 GET、POST、PUT、DELETE
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
// 允许的请求头,如 Content-Type
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
// 是否允许携带凭证信息(如 Cookie)
response.setHeader("Access-Control-Allow-Credentials", "true");
// 预检请求的缓存时间,单位为秒。在此时间范围内,浏览器无需再次发起预检请求
response.setHeader("Access-Control-Max-Age", "3600");
// 继续执行过滤器链
filterChain.doFilter(request, response);
}
}
2.nginx配置方法
在nginx.conf中稍微添加配置即可:
location / {
# 允许跨域的请求,可以自定义变量$http_origin,*表示所有
add_header 'Access-Control-Allow-Origin' *;
# 允许携带cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
# 允许跨域请求的方法:GET,POST,OPTIONS,PUT
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT';
# 允许请求时携带的头部信息,*表示所有
add_header 'Access-Control-Allow-Headers' *;
# 允许发送按段获取资源的请求
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
# 一定要有!!!否则Post请求无法进行跨域!
# 在发送Post跨域请求前,会以Options方式发送预检请求,服务器接受时才会正式请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
# 对于Options方式的请求返回204,表示接受跨域请求
return 204;
}
}