后端跨域问题的处理

news2025/1/23 8:10:32

问题描述

在做前后端分离的项目时,很有可能会遇到这样一种情况:

就是在游览器中请求后端的接口,出现了 CORS error 错误

在这里插入图片描述

报错信息如下:

Access to XMLHttpRequest at 'http://localhost:8860/user/auth/login' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

大概的意思就是:

跨源资源共享(CORS)策略阻止了来自端口 5173 的前端应用对运行在端口 8860 的后端服务的 XMLHttpRequest 请求


原因分析

它的产生并不是因为后端代码出错了,也不是因为前端调用时有问题,而是因为游览器的安全机制(同源策略限制)所导致的,是一个很典型的跨域问题

那游览器的同源策略是什么?

浏览器的 同源策略(Same-origin policy) 是一种安全策略,它规定了从同一个 源(origin) 加载的文档或脚本如何与来自另一个源的资源进行交互。这是浏览器提供的一个重要的安全机制,用于隔离潜在恶意文档,减少可能被攻击的媒介。

同源是指 协议 + 域名 + 端口 三者相同,也就是说,如果两个页面的协议、域名或端口中有任何一个不相同,那么它们就是不同源的。

同源策略主要限制了以下几个方面:

  • Cookie、LocalStorage 和 IndexedDB:无法读取不同源的 Cookie、LocalStorageIndexedDB,这防止了恶意网站窃取或篡改用户的敏感数据
  • DOM:无法操作不同源的页面的 DOM。这确保了恶意网站不能篡改或窃取其他网站的内容
  • AJAX 请求:默认情况下,无法发送 AJAX 请求到不同源的服务器,这防止了恶意网站发起跨站请求伪造( CSRF )攻击

什么是跨域?

跨域就是违法了同源策略,当一个页面去请求另外一个 URL 时,两者 URL协议 + 域名 + 端口 出现不一致

回到上述案例,从控制台中打印的错误信息就能看出,在 http://localhost:5173 的服务中访问了 http://localhost:8860 下的 /user/auth/login 接口,其端口就出现了不一致,出现了跨域


解决方案

现在知道了这种错误是因为跨域问题造成的,那么如何解决这种跨域问题呢?

解决跨域的方法有很多,这里简单介绍以下三种方法:

  • 方案一:Jsonp

    这种方法是早期的一种跨域解决方案,它对各个游览器的版本兼容性做得比较好,但是实现需要前端跟后端都去写相应的代码来进行支持,耦合度高,而且仅支持 GET 请求,所有不常用目前也不推荐用

    比如说在前端使用 ajax 去发送一个请求,需要指定 dataTypeJsonp,这时请求就会自动加上 callback=xxx 这样的参数,xxx 会作为密钥的形式传到后端 ,后端再将 xxx 返回给前端,这就相当于前后端做了一个校验,使得游览器认可这种跨域请求,就可以进行跨域访问了

    前端代码示范:

    $.ajax((
    	url: 'http://localhost:8860/user/auth/login',
    	dataTpe: "jsonp",
    	// Jsonp: 'callback', // 不指定默认 callback
    	// JsonpCallBack: "xxx", // 不指定自动生成
    	type: 'GET',
    	success: function(result) {
    		alert(result.data)
    	}
    ));
    

    后端代码示范:

    	@GetMapping("/jsonp/{id}")
    	public JSONPObject getUser(@PathVariable Integer id, String callback) {
    		return new JSONPObject(callback, new Result<>(200, "success", data))
    	}
    
  • 方式二:Proxy 代理

    使用代理服务器处理跨域问题的基本思路是,在前端和后端服务之间设置一个代理服务器。这个代理服务器位于前端应用所在的域上,因此可以绕过浏览器的同源策略限制。前端应用向代理服务器发送请求,代理服务器再将这些请求转发给实际的后端服务。后端服务处理请求后,将响应返回给代理服务器,代理服务器再将响应转发给前端应用。这样,前端应用看起来就像是直接与后端服务通信,但实际上所有的通信都是通过代理服务器进行的

    现在前端的框架一般都带有 proxy 反向代理功能,就是前端开发的时候一般会在本地启动一个 node.js 服务,让 node 服务去请求接口,然后再把数据传给游览器,就相当于在本地起了一个服务作为中转站

    示例:在 vite.config.ts 文件中配置代理

    export default defineConfig({
      plugins: [vue()],
      server: {
       // 设置项目端口
       port: 5173,
      // 运行时自动打开游览器
      open: true,
      proxy: {
        '/api': {
           // 目标服务器地址
           target: 'http://localhost:8860',
           // 是否改变源地址
           changeOrigin: true,
           // 重写路径
           rewrite: (path) => path.replace(new RegExp('^' + '/api'), ''),
         },
       },
      },
    })
    
  • 方式三:跨域请求 CORS

    CORS(Cross-Origin Resource Sharing) 是一种计算机安全机制,它允许不同源(即协议、域名和端口不同)的 Web 站点进行资源共享。由于浏览器的同源安全策略,通常情况下,一个域的脚本无法直接访问另一个域的资源。CORS 通过在服务器端设置特定的 HTTP 头部,来告诉浏览器:“我允许这个域的脚本访问我的资源”。这样,浏览器就会解除对跨域请求的限制,从而允许前端应用从不同的域请求资源。

    在这里插入图片描述

    CORS 主要有两种模型:

    • 简单模型: 支持 GET、POST、PUT、DELETE 请求,但不允许自定义 header 且会忽略 cookiesPOST 数据格式也有限制,主要支持 text/plain、application/x-www-form-urlencodedmultipart/form-data。其中 text/plain 是默认支持的,后两者需要与服务器进行预检请求和协商
    • 协商模型/预检请求: 当发出如 POST 请求时,浏览器会首先发出一个 OPTIONS 请求进行预检。如果服务器返回 Access-Control-Allow-OriginAccess-Control-Allow-Methods 等头部,并同意来自某个域的请求,浏览器就会继续发出真正的请求

    CORS 从具体的代码实现上来说还是比较方便的,前端不需要编写任何代码,主要是靠服务端进行配置

    CORS 需要游览器和服务器同时支持,目前几乎所有的游览器都支持该功能,IE 游览器不能低于 IE 10

    同时 CORS 也是比较推荐的一种处理跨域请求的做法,具体实现请看后文


代码实现

上述的三种解决跨域的方案中 CORS 是可以完全由后端去实现的,以下内容我就以 Spring BootSpring Cloud 为例概述如何解决跨域问题

这里我在后台启动一个 Spring Cloud 的项目,其中有个 Gateway 服务和一个 User 服务,用户服务中有一个接口 /auth/loign

在这里插入图片描述

如果仅仅看 User 服务它就是一个 Spring Boot 的项目,访问该接口的 URL 为:POST http://localhost:8868/auth/login

Spring Cloud 项目的话一般请求都是走网关的,这里正确的请求 URL 为:POST http://localhost:8860/user/auth/login

前端发送请求代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>发送请求</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.7.2/axios.js"></script>
</head>

<body>

    <button id="bootNpde">Spring Boot 跨域请求</button>
    <button id="cloudNode">Spring Cloud 跨域请求</button>


    <script>

        bootNpde.onclick = function () {
            const p = axios.post("http://localhost:8868/auth/login", {
                username: "admin",
                password: "admin"
            });
            console.log(p);
            p.then(result => {
                console.log(result);
                // 获取服务器端的响应数据
                const { data } = result;
                console.log(data);
            }).catch(err => {
                console.log(err);
            })
        }

        cloudNode.onclick = function () {
            const p = axios.post("http://localhost:8860/user/auth/login", {
                username: "admin",
                password: "admin"
            });
            console.log(p);
            p.then(result => {
                console.log(result);
                // 获取服务器端的响应数据
                const { data } = result;
                console.log(data);
            }).catch(err => {
                console.log(err);
            })
        }

    </script>

</body>

</html>

目前项目没有做任何的跨域处理,所以访问这两个 URL 的时候均会出现跨域错误

在这里插入图片描述

(1)Spring Boot 跨域处理

  • 方式一:在接口或者方法上通过注解 @CrossOrigin 来解决跨域问题

@CrossOrigin 注解是 Spring 框架中的一个注解,它的主要作用是处理跨域资源共享(CORS)问题

使用 @CrossOrigin 注解,可以在控制器类或具体处理方法上指定哪些来源可以访问该类或方法,从而实现对 CORS 的简化配置。当在类或方法上使用此注解时,Spring 会自动在 HTTP 响应头中添加适当的 CORS 相关头部信息,如 Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers 等,从而允许浏览器执行跨域请求

@CrossOrigin 注解支持多种配置选项,例如允许特定来源、允许所有来源、指定请求头和响应头等。例如,可以在注解中指定 origins 属性来限制可以访问的域名列表,或使用 methods 属性来指定允许的 HTTP 请求方法

代码示例:

@Slf4j
@RestController
@RequestMapping("/auth")
@Api(tags = "【登录认证】")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.GET})
public class AuthController {

    private final AuthService authService;

    @PostMapping(value = "/login")
    @ApiOperation(value = "用户登录")
    //@CrossOrigin(origins = "http://localhost:5173", methods = {RequestMethod.POST, RequestMethod.GET})
    public ResponseBean<LoginResp> login(@RequestBody @Validated LoginReq req) {
        return ResponseBean.success(authService.login(req));
    }
}

测试:

在这里插入图片描述

  • 方式二:配置全局 CORS 映射

如果你希望全局地配置 CORS 策略,可以在 Spring Boot 配置类中添加一个 CORS 配置 bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {

        CorsConfiguration config = new CorsConfiguration();
        // 允许向该服务器提交请求的 URI,* 表示全部允许,在 SpringMVC 中,如果设成 *,会自动转成当前请求头中的 Origin
        //config.addAllowedOrigin("*");
        // 指定允许跨域的域名
        //config.addAllowedOrigin("http://localhost:5173");
        // springboot2.4.2 中 addAllowedOrigin 不允许设置为 *,要改成使用 AllowedOriginPattern
        config.addAllowedOriginPattern("*");
        // 允许访问的头信息,* 表示全部
        config.addAllowedHeader("*");
        // 允许提交请求的方法,*表示全部允许
        config.addAllowedMethod("*");
        // 允许 cookies 跨域
        config.setAllowCredentials(true);
        // 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
        config.setMaxAge(18000L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

或者写成:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry
                        // 映射到所有路径
                        .addMapping("/**")
                        // 允许所有域名进行跨域调用
                        //.allowedOrigins("*")
                        // springboot2.4.2 后 addAllowedOrigin 不允许设置为 *,要改成使用 AllowedOriginPattern
                        .allowedOriginPatterns("*")
                        // 允许所有请求方式跨域调用
                        .allowedMethods("*")
                        // 放行全部原始头信息
                        .allowedHeaders("*")
                        // 允许携带 Cookie 信息
                        .allowCredentials(true)
                        // 预检请求的缓存时间
                        .maxAge(18000L);
            }
        };
    }

}

测试:

在这里插入图片描述

(2)Spring Cloud 跨域处理

  • 方式一:配置全局 CORS 映射

Spring boot 配置全局 CORS 差不多,不过是在 Gateway 服务的配置类中添加一个 CORS 配置 bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

/**
 * 跨域处理
 */
@Configuration
public class GlobalCorsConfiguration {

    @Bean
    public CorsWebFilter corsFilter() {
        // 配置跨域信息
        CorsConfiguration config = new CorsConfiguration();
        // 允许跨域的请求来源:允许所有域名进行跨域调用
        config.addAllowedOriginPattern("*");
        // 允许跨域的头:放行全部原始头信息
        config.addAllowedHeader("*");
        // 允许跨域的请求方式:允许所有请求方式跨域调用
        config.addAllowedMethod("*");
        // 允许携带 Cookie 信息
        config.setAllowCredentials(true);

        // 添加映射路径
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        // 任意 url 都要进行跨域配置
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }

}

在这里插入图片描述

  • 方式二:在配置文件中设置 CORS 策略

Gateway 服务的配置文件 application.yml 中设置 CORS 策略

示例:

spring:
  cloud:
    gateway:
      # 全局的跨域处理
      globalcors: 
        # 解决 options 请求被拦截问题
        add-to-simple-url-handler-mapping: true 
        cors-configurations:
          '[/**]':
            allowedOrigins:  # 允许哪些网站的跨域请求
              - "http://localhost:5173"
            allowedMethods:  # 允许的跨域 ajax 的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            # 允许在请求中携带的头信息  
            allowedHeaders: "*"
            # 是否允许携带 cookie
            allowCredentials: true
            # 这次跨域检测的有效期
            maxAge: 36000

需要注意的问题:

对于 Spring Cloud Gateway,你可以通过全局 CORS 配置或者特定路由的 CORS 配置来设置 CORS。确保没有其他过滤器或配置在之后覆盖了你的 CORS 设置

也就是说最好只配置一个 CORS,比如你在配置文件中配置了全局跨域处理,允许 http://localhost:5173 进行跨域,那么就不要用 @CrossOrigin 在接口上设置了 CORS

例如:

@Slf4j
@RestController
@RequestMapping("/auth")
@Api(tags = "【登录认证】")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.GET})
public class AuthController {

    private final AuthService authService;

    @PostMapping(value = "/login")
    @ApiOperation(value = "用户登录")
    //@CrossOrigin(origins = "http://localhost:5173", methods = {RequestMethod.POST, RequestMethod.GET})
    public ResponseBean<LoginResp> login(@RequestBody @Validated LoginReq req) {
        return ResponseBean.success(authService.login(req));
    }
}

不然就会因为响应头 Access-Control-Allow-Origin 包含多个值时,被浏览器拒绝该响应

在这里插入图片描述

在这里插入图片描述

报错信息:

Access to XMLHttpRequest at 'http://localhost:8860/user/auth/login' from origin 'http://localhost:5173' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:5173, *', but only one is allowed.

这样就导致了即使你配置了跨域,但是还是会出现跨域的问题的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1821191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见的 EVM 版本以及它们的区别

EVM&#xff08;以太坊虚拟机&#xff09;版本的演进是为了引入新的特性和改进以太坊平台的安全性、效率和功能性。每个版本通常伴随着以太坊网络的硬分叉&#xff0c;这是以太坊协议的重大升级。以下是一些常见的EVM版本及其主要区别&#xff1a; Homestead (2016年3月)&…

图像生成新篇章:Stable Diffusion 3 Medium开源评析

摘要 在数字艺术与人工智能的交汇点上&#xff0c;Stable Diffusion 3&#xff08;SD3&#xff09;的开源无疑是一场技术革新的盛宴。就在3月份&#xff0c;我撰写了一篇博文&#xff0c;深入探讨了SD3的技术报告内容与介绍&#xff0c;文章发表在CSDN博客上&#xff0c;https:…

同城如何异地共享文件?

在现代社会中&#xff0c;跨地区的合作变得越来越普遍&#xff0c;而这也带来了共享文件的需求。当我们身处不同的城市&#xff0c;如何高效地共享文件已经成为一项迫切的需求。本文将介绍一种名为“同城异地共享文件”的解决方案&#xff0c;帮助解决这一问题。 2. 天联组网—…

Day02 顺序表

目录 1、顺序表 2、随机访问&顺序访问 3、思考 4、顺序表的封装 1、顺序表 数组在数据结构中是属于线性表的一种&#xff0c;线性表是由一组具有n个相同类型的数据元素组成的。线性表中的任何一个数据元素 有且只有一个直接前驱有且只有一个直接后继首元素是没有前驱的…

学习Java中的Future类

学习Java中的Future类 Future接口在Java 5中引入&#xff0c;作为java.util.concurrent包的一部分。它代表一个异步计算的结果&#xff0c;当计算完成时可以通过Future对象获取结果。Future对象提供了一些方法来检查任务是否完成、等待任务完成并获取任务结果、取消任务等。 …

【python】tkinter编程三大布局管理器pack、grid、place应用实战解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

leetcode240 搜索二维矩阵II

题目 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18…

redis序列化

文章目录 1、为什么要进行序列化操作&#xff1f;2、序列化方式2.1、自定义序列化2. 2、StringRedisTemplate&#xff08;重点&#xff09; 1、为什么要进行序列化操作&#xff1f; 不进行序列化向redis存入数据代码&#xff1a; SpringBootTest class RedisDemoApplicationT…

渗透测试练习题解析 6 (CTF web)

1、[HCTF 2018]admin 1 考点&#xff1a;二次注入 先注册一个账号看看&#xff0c;注册 admin 会提示该用户名已存在&#xff0c;那我们就换一个用户名 观察页面功能&#xff0c;存在一个修改密码&#xff0c;开始的思路是想看看能否通过该密码功能抓包然后修改用户名为 admin …

RAG_Example

今天尝试基于langchain进行LLM RAG搭建&#xff0c;感觉使用难度没有想象中大。具体流程参考末尾链接。 主要流程包括下面几个模块&#xff0c;每一个模块都有很多选择&#xff0c;而不是唯一解。 但这里可以感受到潜在的几个问题 1. 文本转换过程中&#xff0c;PDF的信息可…

Android framework的Zygote源码分析

文章目录 Android framework的Zygote源码分析linux的fork Android framework的Zygote源码分析 init.rc 在Android系统中&#xff0c;zygote是一个native进程&#xff0c;是Android系统上所有应用进程的父进程&#xff0c;我们系统上app的进程都是由这个zygote分裂出来的。zyg…

极限网关助力好未来 Elasticsearch 容器化升级

极限网关在好未来的最佳实践案例&#xff0c;轻松扛住日增百 TB 数据的流量&#xff0c;助力 ES 从物理机到云原生架构的改造&#xff0c;实现了流控、请求分析、安全管理、无缝迁移等场景。一次完美的客户体验~ 背景 物理机架构时代 2022 年&#xff0c;好未来整个日志 Elas…

开源AGV调度系统OpenTCS中的路由器(router)详解

OpenTCS中的任务分派器router详解 1. 引言2. 路由器(router)2.1 代价计算函数&#xff08;Cost functions&#xff09;2.2 2.1 Routing groups2.1 默认的停车位置选择2.2 可选停车位置属性2.3 默认的充电位置选择2.4 即时运输订单分配 3. 默认任务分派器的配置项4. 参考资料与源…

区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测

区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测 目录 区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测效果一览基本介绍程序设计参考资…

Java——IO流(一)-(4/8):前置知识-字符集、UTF-8、GBK、ASCII、乱码问题、编码和解码等

目录 常见字符集介绍 标准ASCII字符集 GBK&#xff08;汉字内码扩展规范&#xff0c;国标&#xff09; Unicode字符集&#xff08;统一码&#xff0c;万国码&#xff09; 小结 字符集的编码、解码操作 方法 实例演示 常见字符集介绍 标准ASCII字符集 ASCll(American St…

python数据分析--- ch8-9 python函数及类

python数据分析--- ch8-9 python函数及类 1. Ch8--函数1.1 函数的定义1.2 形参与实参1.2.1 使用位置参数调用函数1.2.2 使用关键字参数调用函数 1.3 参数的默认值1.4 可变参数(*)1.4.1 基于元组的可变参数(* 可变参数)1.4.2 基于字典的可变参数(** 可变参数) 1.5 函数中变量的作…

【PHP开发工程师系统性教学】——thinkPHP的分页操作,不管有几页,用这个你想分几页就分几页

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

【单片机毕业设计选题24005】-基于STM32的智能家居环境监测系统

系统功能: 此设计采用STM32单片机将采集到的环境环境温湿度,光照强度,火焰传感器状态,烟雾值,空气质量值等数据显示在OLED上&#xff0c;并将这些信息通过上报至手机APP。系统可通过手机蓝牙APP修改各传感器阈值. 蓝牙连接后&#xff0c;如果系统处于自动状态则每隔5秒钟上报…

多表联查小情景例子

这里有个需求&#xff1a; 需要给定套餐表setmeal 的 id 查询这个套餐内的所有菜品 dish 实际上如果可能&#xff0c;只需要查询套餐菜品表(setmeal_dish)&#xff0c;查看一个套餐内包含包含的所有菜品&#xff0c;然后把这些菜品全部取出即可。 看一下setmeal_dish 表&…

水泥行业超低排放简介

在当今社会&#xff0c;随着环保意识的不断提高&#xff0c;水泥行业作为重要的工业领域&#xff0c;其超低排放的实施范围及成效日益受到人们的关注。朗观视觉小编将从多个角度探讨水泥行业超低排放的实施范围&#xff0c;分析其背后的意义与影响&#xff0c;展望未来的发展趋…