跨域(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设置跨域请求头:

  1. 安装和配置Nginx;
  2. 编辑Nginx文件;
  3. 设置跨域设置;
复制代码
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
  }
}
复制代码

 

 


 

posted @   学Java的`Bei  阅读(808)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
点击右上角即可分享
微信分享提示