WEB项目解决CORS 跨域问题

2024-09-05 15:12

本文主要是介绍WEB项目解决CORS 跨域问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        为了安全,web默认是不允许跨域访问的。不过实际项目中,会遇到不同模块之间来回跳转的情况。所以,项目内部一般会修改配置或者代码来解决CORS跨域问题。

        我的后端使用的是 Jetty 服务器,所以下面就拿jetty来举例。Jetty 提供了一个 CrossOriginFilter 类,可以用来配置和管理跨域请求。

在 Jetty 中配置 CORS

下面有三种配置方式,一种是在web.xml中直接配置,无需修改代码。另外两种是在java代码中配置,这种适合没有web.xml的场景。

方法一. 修改 web.xml 文件

如果项目使用的是 web.xml 文件来配置 servlet,可以通过在 web.xml 中添加以下内容来配置 CORS 过滤器:

<filter><filter-name>cross-origin</filter-name><filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class><init-param><param-name>allowedOrigins</param-name><param-value>*</param-value> <!-- 允许所有域,如果需要限制可以具体指定 --></init-param><init-param><param-name>allowedMethods</param-name><param-value>GET,POST,HEAD,OPTIONS</param-value> <!-- 允许的HTTP方法 --></init-param><init-param><param-name>allowedHeaders</param-name><param-value>X-Requested-With,Content-Type,Accept,Origin</param-value> <!-- 允许的请求头 --></init-param><init-param><param-name>preflightMaxAge</param-name><param-value>1800</param-value> <!-- 预检请求的最大缓存时间,单位为秒 --></init-param><init-param><param-name>allowCredentials</param-name><param-value>true</param-value> <!-- 是否允许凭证 --></init-param>
</filter><filter-mapping><filter-name>cross-origin</filter-name><url-pattern>/*</url-pattern> <!-- 过滤器适用的URL模式 -->
</filter-mapping>

方法二. 使用 Java 代码配置 CORS 过滤器

如果使用的是 Java 代码配置 Jetty 而不是 web.xml 文件,可以使用以下代码来配置 CrossOriginFilter

import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;// 创建 Jetty 服务器实例
Server server = new Server(8080);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");// 创建并配置 CORS 过滤器
FilterHolder cors = new FilterHolder(CrossOriginFilter.class);
cors.setInitParameter("allowedOrigins", "*"); // 允许所有来源
cors.setInitParameter("allowedMethods", "GET,POST,HEAD,OPTIONS"); // 允许的HTTP方法
cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin"); // 允许的请求头
cors.setInitParameter("allowCredentials", "true"); // 是否允许凭证// 将 CORS 过滤器添加到 Jetty 上下文
context.addFilter(cors, "/*", EnumSet.of(DispatcherType.REQUEST));
server.setHandler(context);// 启动服务器
server.start();
server.join();

CrossOriginFilter依赖jetty-servlets.jar。

参数解释

  • allowedOrigins: 设置允许的来源(Origin)。可以是具体的 URL,或者使用 * 表示允许所有来源。为了安全,生产环境中建议指定具体的域。

  • allowedMethods: 定义允许的 HTTP 方法(如 GET, POST, OPTIONS 等)。

  • allowedHeaders: 设置允许的请求头。如果需要处理自定义头部,可以在这里添加。

  • allowCredentials: 表示是否允许发送 Cookie 等凭证信息。如果为 true,则 allowedOrigins 不能是 *,需要指定具体的域。

  • preflightMaxAge: 设置浏览器在发送下一个预检请求之前缓存 OPTIONS 请求的时间。

方法三. 自定义 AccessControlFilter 实现

除了配置CrossOriginFilter,还可以自定义 ContainerResponseFilter 的实现类。只要确保自定义类处理了 CORS 请求的核心逻辑即可,下面的代码是定义了一个实现类AccessControlFilter:

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;@Provider
public class AccessControlFilter implements ContainerResponseFilter {@Overridepublic void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {// 设置允许的来源responseContext.getHeaders().add("Access-Control-Allow-Origin", "*"); // 可以根据需求修改为具体域名// 设置允许的HTTP方法responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, HEAD");// 设置允许的请求头responseContext.getHeaders().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept, Origin");// 是否允许凭证responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");// 预检请求的缓存时间responseContext.getHeaders().add("Access-Control-Max-Age", "1209600"); // 14天}
}

如何使用 AccessControlFilter

  • 如果使用的是 Java 配置类,代码如下:
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {public JerseyConfig() {packages("你的包名");register(AccessControlFilter.class);}
}
  • 如果使用 web.xml,web.xml 中配置
    <servlet><servlet-name>jersey-servlet</servlet-name><servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class><init-param><param-name>jersey.config.server.provider.packages</param-name><param-value>你的包名</param-value></init-param><init-param><param-name>jersey.config.server.provider.classnames</param-name><param-value>com.example.AccessControlFilter</param-value></init-param><load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping><servlet-name>jersey-servlet</servlet-name><url-pattern>/api/*</url-pattern>
    </servlet-mapping>
    

处理 OPTIONS 请求

CORS 预检请求通常使用 OPTIONS 方法。在 AccessControlFilter 中添加对 OPTIONS 请求的处理,以确保预检请求能够成功返回。

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.core.Response;
import java.io.IOException;@Provider
public class AccessControlFilter implements ContainerResponseFilter {@Overridepublic void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {// 设置 CORS 响应头responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, HEAD");responseContext.getHeaders().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept, Origin");responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");// 处理 OPTIONS 预检请求if (requestContext.getMethod().equalsIgnoreCase("OPTIONS")) {responseContext.setStatusInfo(Response.Status.OK);}}
}

如果不想处理options请求, 可以通过在web服务器侧,配置正向和反向代理,将后端的url都映射成一个apache侧的url。具体实现方法可参考对应的web服务器,这里就不再赘述了。

这篇关于WEB项目解决CORS 跨域问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139315

相关文章

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出

如何在Spring Boot项目中集成MQTT协议

《如何在SpringBoot项目中集成MQTT协议》本文介绍在SpringBoot中集成MQTT的步骤,包括安装Broker、添加EclipsePaho依赖、配置连接参数、实现消息发布订阅、测试接口... 目录1. 准备工作2. 引入依赖3. 配置MQTT连接4. 创建MQTT配置类5. 实现消息发布与订阅

springboot项目打jar制作成镜像并指定配置文件位置方式

《springboot项目打jar制作成镜像并指定配置文件位置方式》:本文主要介绍springboot项目打jar制作成镜像并指定配置文件位置方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录一、上传jar到服务器二、编写dockerfile三、新建对应配置文件所存放的数据卷目录四、将配置文

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到