解决前后端分离架构中跨域问题

这篇具有很好参考价值的文章主要介绍了解决前后端分离架构中跨域问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前后端分离架构中,前端调用后端提供的API接口来获取数据。由于浏览器的 同源策略要求当前请求与目标请求的域名、协议、端口都要相同,而前端服务与后端服务往往会被部署到不同的机器,不同端口上,因此会产生跨域问题。

1. 为什么产生跨域问题

(1)同源策略

同源策略是由 Netscape 提出的一个著名的安全策略,它是浏览器最核心也是最基本的安全功能,所有支持 JavaScript 的浏览器都会使用这个策略。在同源策略中,要求当前请求与目标请求的域名、协议、端口都要相同。 同源策略具体规则如下表:
解决前后端分离架构中跨域问题

(2)非跨域请求与跨域请求

非跨域请求,在请求头中会只包含请求的主机名。

解决前后端分离架构中跨域问题
跨域请求,在请求头中会既包含要请求的主机名还包括当前的源主机名

解决前后端分离架构中跨域问题

2.浏览器对请求的分类

HTTP1.1 协议中,请求方法分为 GETPOSTPUTDELETEHEADTRACEOPTIONSCONNECT 八种。浏览器根据请求方法和请求类型将请求划分为 简单请求非简单请求

(1)简单请求:浏览器先发送请求再判断是否跨域

  • 请求方法为 GETPOSTHEAD
  • Request Headers 中无自定义的请求头信息
  • Content-Type 为 text/plainmultipart/form-dataapplication/x-www-form-urlencoded

(2)非简单请求:浏览器先发送预检命令(OPTIONS 请求方法),检查通过后才发送真正的数据请求

预检请求 Headers:

  • Access-Control-Request-Headers: content-type,x-token
    • 指明实际请求所携带的字段
  • Access-Control-Request-Method: POST
    • 指明实际请求所使用的 HTTP 方法

预检响应 Header:

  • Access-Control-Allow-Origin: http://localhost:8080
    • 指明允许访问的域。
  • Access-Control-Allow-Methods: POST
    • 指明允许的 HTTP 请求方法。
  • Access-Control-Allow-Headers: content-type, x-token
    • 指明允许携带的字段。
  • Access-Control-Max-Age: 3600
    • 指明该响应的有效时间,在有效时间内,浏览器无须为同一请求再次发起预检请求。浏览器检查预检响应信息,如果预检通过就发送实际请求。使用预检请求可以避免跨域请求对服务器的数据产生未预期的影响。

请求方法为 PUTDELETE 的 AJAX 请求、发送 JSON 格式的 AJAX 请求、带自定义头的 AJAX 请求都是非简单请求。

3.解决跨域问题

Nginx部署: 195.128.10.1:8080
前端服务部署: 195.128.10.1:9528
后端服务1部署: 195.128.10.2:8989
后端服务2部署: 195.128.10.2:8999
后端服务3部署: 195.128.10.2:9999

(1)nginx中配置地址转发

用户访问 Nginx 地址http://195.128.10.1:8080,前端访问的后端地址为http://195.128.10.1:8080/resource1 ,http://195.128.10.1:8080/resource2,http://195.128.10.1:8080/resource3。Nginx根据url转发。

注意:proxy_set_header 是 nginx 设置请求头给上游server服务器

server
{
    listen       8080;
    server_name localhost;
    
    location /js {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://192.168.137.189:8081/; # 转发地址
    }
	location /resource1 {
        proxy_pass http://195.128.10.2:8989; # 转发地址
        proxy_read_timeout 600s;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $host:$se;
    }
	location /resource2 {
        proxy_pass http://195.128.10.2:8999; # 转发地址
        proxy_read_timeout 600s;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $host:$se;
    }
    location /resource3 {
        proxy_pass http://195.128.10.2:9999; # 转发地址
        proxy_read_timeout 600s;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $host:$se;
    }
}

(2)nginx中添加允许跨域请求头

用户访问前端地址http://195.128.10.1:9528,前端访问Nginx地址http://195.128.10.1:8080/resource1 ,http://195.128.10.1:8080/resource2,http://195.128.10.1:8080/resource3,Nginx根据URL转发。

注意:add_header是nginx设置响应头信息给浏览器

server {
    listen       8080;
    server_name  localhost;
    location  /resource1  {
        add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
        add_header Access-Control-Allow-Headers '*';
        add_header Access-Control-Allow-Methods '*';
        add_header Access-Control-Allow-Credentials 'true';
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        proxy_pass  http://195.128.10.2:8989;
    }
    location  /resource2  {
        add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
        add_header Access-Control-Allow-Headers '*';
        add_header Access-Control-Allow-Methods '*';
        add_header Access-Control-Allow-Credentials 'true';
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        proxy_pass  http://195.128.10.2:8999;
    }
    location  /resource3  {
        add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
        add_header Access-Control-Allow-Headers '*';
        add_header Access-Control-Allow-Methods '*';
        add_header Access-Control-Allow-Credentials 'true';
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        proxy_pass  http://195.128.10.2:9999;
    }
}

(3)后端解决跨域问题

https://blog.csdn.net/m0_71777195/article/details/126830773

通过配置文件跨域

创建一个新配置文件;添加 @Configuration 注解,实现 WebMvcConfigurer 接口;重写 addCorsMappings 方法,设置允许跨域的代码。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedOriginPatterns("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

通过 CorsFilter 跨域

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setMaxAge(3600L);
        return corsConfiguration;
    }
    
	@Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }    
}

ResponseBodyAdvice

通过重写 ResponseBodyAdvice 接口中的 beforeBodyWrite(返回之前重写)方法,可以对所有的接口进行跨域设置文章来源地址https://www.toymoban.com/news/detail-406674.html

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * 内容是否需要重写(通过此方法可以选择性部分控制器和方法进行重写)
     * 返回 true 表示重写
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
    /**
     * 方法返回之前调用此方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 设置跨域
        response.getHeaders().set("Access-Control-Allow-Origin", "*");
        return body;
    }
}

到了这里,关于解决前后端分离架构中跨域问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前后端分离项目跨域问题No ‘Access-Control-Allow-Origin‘解决方案

    一.问题背景 前后端分离项目跨域问题,浏览器控制台报错: No \\\'Access-Control-Allow-Origin\\\' header is present on the requested resource. 请求方法为OPTIONS,状态值为302或403。 本文解决常见的CORS跨域问题,以及,集成CAS 5.3单点登录内嵌页面时,发送复杂请求产生的跨域问题。 二.解决方案

    2024年02月02日
    浏览(54)
  • Spring Boot学习随笔- 后端实现全局异常处理(HandlerExceptionResolver),前后端解决跨域问题(@CrossOrigin(局部解决)自定义跨域配置类(全局))

    学习视频:【编程不良人】2021年SpringBoot最新最全教程 异常处理作用:用来解决整合系统中任意一个控制器抛出异常时的统一处理入口 传统单体架构下的处理方式 配置全局异常处理类 resolveException :当控制器方法出现异常时,如果该方法没有try...catch,则会进入当前方法 针

    2024年02月04日
    浏览(66)
  • SpringBoot 配置CORS处理前后端分离跨域配置无效问题解析

    浏览器有跨域限制,非同源策略(协议、主机名或端口不同)被视为跨域请求,解决跨域有跨域资源共享( CORS )、反向代理和 JSONP 的方式。本篇通过 SpringBoot 的资源共享配置(CORS)来解决前后端分离项目的跨域,以及从原理上去解决跨域配置不生效的问题。 使用前后端分离开源项

    2023年04月23日
    浏览(52)
  • java中跨域问题

    Java 中的跨域问题指的是在使用 AJAX 技术进行跨域访问时,由于浏览器的安全限制,导致请求被拒绝或者无法获取到正确的响应结果。 解决 Java 中的跨域问题可以采用以下几种方式: 1、通过设置响应头信息来支持跨域访问。 在 Java 中可以通过设置响应头信息来支持跨域访问

    2024年02月11日
    浏览(42)
  • SpringSecurity-2.7中跨域问题

    SpringSecurity-2.7中跨域问题 访问测试 起因 写这篇的起因是会了解到 SSM(@CrosOrigin) 解决跨域,但是会在加入 SpringSecurity 配置后,这个跨域解决方案就失效了,而 /login 这个请求上是无法添加这个 注解 或者 通过配置(WebMvcConfig) 去解决跨域,所以只能使用 SpringSecurity 提供的 .cros() 去解

    2024年02月03日
    浏览(42)
  • 前后端分离 后端获取不到header解决方案

    我这里只是把重要的逻辑放在里面,如果要看所有文件的话就太多了 这个案例不要拿来用,这个是有问题的,我只是讲一下问题在哪

    2024年02月12日
    浏览(65)
  • asp.net core 6中跨域问题

    1.在使用 .net 6 开发WEBAPI程序时,出现跨域问题 。原来的写法不能用了。用下面的写法解决问题 builder.Services.AddCors(options = {     options.AddPolicy(\\\"any\\\", builder =     {         builder.SetIsOriginAllowed(_ = true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();     }); });   app.UseCors(\\\"any\\\");

    2024年02月16日
    浏览(63)
  • 解决前后端分离项目后端设置响应头前端无法获取

    在开发前后端分离项目中出现后端设置响应头,前端一直无法获取等问题。 后端设置响应头代码如下 在浏览器中我们是可以看到设置的响应头 Content-Disposition 属性,但是在前端接收到的响应信息中却看不到我们设置的 Content-Disposition 属性。 原来在前后端分离的项目中除了需

    2024年02月04日
    浏览(64)
  • 大型医院云HIS系统:采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发 融合B/S版电子病历系统

    一套医院云his系统源码 采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发。融合B/S版电子病历系统,支持电子病历四级,HIS与电子病历系统均拥有自主知识产权。 文末卡片获取联系! 基于云计算技术的B/S架构的医院管理系统(简称云HIS),采用前后

    2024年02月03日
    浏览(50)
  • nginx如何解决前后端跨域问题

    Nginx 可以通过以下两种方式来解决前后端跨域问题: 添加 CORS 头部 Nginx 可以通过添加 CORS 头部来解决跨域问题。CORS(Cross-Origin Resource Sharing)是一种机制,它允许 Web 应用程序从不同的域访问其资源。要在 Nginx 中添加 CORS 头部,可以在 Nginx 配置文件中的特定位置添加以下代

    2024年02月05日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包