解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域

偶尔遇到一个 Tomcat 部署项目跨域问题,因为已经处理过太多跨域了,觉得很简单 。

结果尝试多次均不能达到想要的结果,又经过 Nginx、Tomcat 以及项目配置才完全搞定。

另外,之前总结了篇 Web 项目跨域问题(Geoserver),也可以综合参考。

本文包含 Tomcat 配置允许跨域、Web 项目配置允许跨域以及同时允许跨域三部分。


Tomcat 配置允许跨域

使用 Tomcat 作为静态文件服务还是比较简单和常用的,而跨域问题也比较容易解决。

Tomcat 静态文件允许跨域,设置比较简单,百度一搜一堆,这里简单贴一下。

1.Tomcat web.xml 配置允许所有跨域

设置之后,所有静态文件以及服务均被允许跨域。

(1) 当未配置允许跨域时,报跨域错误

在这里插入图片描述

浏览器直接访问是正常的:

在这里插入图片描述

(2)Tomcat conf/web.xml 文件配置允许跨域

在这里插入图片描述

<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>

</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

配置之后,重启 Tomcat,再次访问则正常:

在这里插入图片描述


Web 项目配置允许跨域

Web 项目,这里指的是 java 项目,打包的时候基本是选择 war 包或者 jar 包。

老项目以 war 包居多,新项目(Springboot)以 jar 包居多。

war 可以直接在 Tomcat 中部署启动,而 jar 包则往往通过命令启动。

因此,war 的跨域相关配置会收到 Tomcat 跨域配置影响。jar 包独立启动,不会受 Tomcat 影响。

这里介绍一下 Web 项目各种允许跨域配置。

1. 未配置允许跨域时,报跨域错误

在这里插入图片描述

而浏览器地址栏直接可以正常访问:

在这里插入图片描述

2. 配置允许跨域

(1)自定义过滤器允许跨域

WEB-INF/web.xml 配置文件允许所有接口跨域,一般不建议这样配置。

<filter>
  <filter-name>cors</filter-name>
  <filter-class>MyCORSFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>cors</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

过滤类,任意目录即可,以根目录为例,其他目录需要加上包路径:

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class MyCORSFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException, IOException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String origin = (String) servletRequest.getRemoteHost()+":"+servletRequest.getRemotePort();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
        response.setHeader("Access-Control-Allow-Credentials","true");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

(2)继承 WebMvcConfigurationSupport 允许跨域

Springboot 框架下的配置,允许所有接口跨域,Springboot 环境下测试生效,Spring MVC环境下测试未生效。

package com.mapsharp.map.web.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.nio.charset.Charset;
import java.util.List;

/**
 * @author
 * @Description: 设置允许跨域访问static资源
 * @date 2019/6/39:26
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        System.out.println("自动配置生效addResourceHandlers");
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }

    //前端跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")//设置允许跨域的路径
                .allowedOrigins("*")//设置允许跨域请求的域名
                .allowedHeaders("*")//是否允许证书 不再默认开启
                .exposedHeaders("Access-Control-Allow-Origin,Access-Control-Allow-Credentials")//是否允许证书 不再默认开启
                .allowCredentials(true)//是否允许证书 不再默认开启
                .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE")//设置允许的方法
                .maxAge(3600);//跨域允许时间
    }

    //为了解决中文编码方式乱码问题
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        converter.setWriteAcceptCharset(false);
        return converter;
    }

    @Bean
    public ObjectMapper getObjectMapper() {
        return new ObjectMapper();
    }

    @Bean
    public MappingJackson2HttpMessageConverter messageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(getObjectMapper());
        return converter;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(responseBodyConverter());
        converters.add(messageConverter());
    }
}

(3)@CrossOrigin 注解允许跨域

注意 Spring 框架版本,测试项目 Spring MVC 和 SpringBoot 均生效。

根据实际需求,选择在 类或者方法 剩添加 @CrossOrigin 注解即可。

这样的好处是,最小颗粒度控制允许跨域。

在这里插入图片描述

在这里插入图片描述


Tomcat 同时允许静态文件和 Web 服务跨域

Tomcat 静态文件和 Web 服务同时允许跨域,即 Tomcat webapp 目录下同时存在静态文件服务和 war 包启动的服务。

开始阶段发现,配置 Web 服务允许跨域之后不生效。但是静态文件可以正常访问。

后来经过测试,要想静态文件和 Web 服务接口都允许跨域,需要以下条件:

1.Tomcat 设置允许所有跨域,开放最大权限

注意下图中红框部分,笔者当时没注意,导致一直没解决问题。

注意:红框部分需要注释掉!

在这里插入图片描述

2.Web 服务不设置任何允许跨域配置(@CrossOrigin注解不影响)

Tomcat 中的 Web 服务,即 war 包中,不能设置允许跨域配置。

但是经过测试 @CrossOrigin注解 可以设置,不影响跨域结果。

在这里插入图片描述


文章小结:如果 Tomcat 和 Web 服务都配置了 web.xml 允许跨域,则会出现冲突,不能解决跨域问题。

在这里插入图片描述

如果只是 Web 项目,则在接口层面进行控制;

如果也需要静态文件和 Web 服务同时允许跨域,则在Tomcat 中进行一次配置即可。

同时配置允许跨域不生效的原因:个人感觉是因为有啥冲突,AI 的回答是:

在这里插入图片描述
在这里插入图片描述


参考博客:

tomcat 设置允许跨域访问

Tomcat解决跨域问题(Access-Control-Allow-Origin,403,404)

<think>首先,用户的问题是:“我想解决Tomcat服务器中的问题 请问Tomcat 配置解决请求问题”。我需要基于系统指令提供的引用信息来回答。 系统指令包括: - 所有行内数学表达式用 $...$ 格式。 - 独立公式用 $$...$$ 格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题- 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题- 尽量保证回答真实可靠。 提供的引用: - [^1]: 解决 Tomcat 问题 - Tomcat 配置静态文件 Java Web 服务同时允许- [^2]: SpringMVC中的请求配置解决方案,包括自定义CorsConfigurationSource。 - [^3]: Tomcat部署GeoServer,OPTIONS请求403问题解决方式,通过编辑web.xml取消CorsFilter注释。 - [^4]: 解决tomcat服务请求问题,使用拦截器设置响应头。 用户的问题是针对Tomcat服务配置解决问题。我需要整合这些引用信息来提供解决方案。 关键点: - 问题(CORS)是由于浏览器的同源策略引起的,需要服务器设置特定的HTTP头来允许请求。 - Tomcat中可以通过配置Filter来设置这些头,或者使用Spring框架的拦截器(如果是Java Web应用)。 步骤: 1. **理解问题**:简要解释是什么,为什么需要解决。 2. **解决方案**: - 方法1:配置Tomcat的CorsFilter(基于引用[^1][^3])。 - 方法2:在Java Web应用中使用拦截器(基于引用[^4])。 - 方法3:使用Spring MVC配置(基于引用[^2])。 3. **详细步骤**:提供具体的配置示例。 4. **注意事项**:提到OPTIONS请求403问题(引用[^3])。 5. **生成相关问题**:在最后添加相关问题部分。 回答结构: - 开头:介绍问题Tomcat中的解决方案。 - 逐步指南: - 步骤1:配置Tomcat的CorsFilter(适用于所有应用)。 - 步骤2:在Web应用中自定义拦截器(适用于特定应用)。 - 步骤3:使用Spring Boot或Spring MVC配置- 结尾:总结。 - 相关问题:生成3-4个相关问题。 确保使用中文回答,并正确添加引用标识。例如,当提到引用内容时,在末尾添加[^1]。 现在,制定回答大纲: 1. **引言**:解释问题Tomcat解决方案。 2. **方法1:配置Tomcat的CorsFilter**: - 编辑web.xml文件。 - 取消CorsFilter的注释并配置参数。 - 参考引用[^1][^3]。 3. **方法2:使用Java Web拦截器**: - 创建拦截器类设置响应头。 - 参考引用[^4]。 4. **方法3:使用Spring MVC配置**: - 自定义CorsConfigurationSource。 - 参考引用[^2]。 5. **注意事项**:处理OPTIONS请求403问题。 6. **相关问题**:生成相关问题。 生成相关问题: 1. 如何测试Tomcat配置是否生效? 2. Tomcat配置中allowed-origins参数的作用是什么? 3. 在Spring Boot中如何配置? 4. 请求的安全风险有哪些? 确保回答真实可靠:基于提供的引用一般知识。</think>### Tomcat 服务问题解决方案 问题(CORS, Cross-Origin Resource Sharing)是由于浏览器的同源策略导致的,当 Web 应用尝试从不同名、端口或协议访问资源时,Tomcat 服务器需要配置特定的 HTTP 头来允许这些请求。以下是解决 Tomcat 问题的逐步指南,基于真实可靠的配置方法。我将从简单到复杂介绍三种常见方案,确保您能根据实际需求选择。 #### 方法 1: 配置 Tomcat 的 CorsFilter(适用于所有 Web 应用) 这是最通用的方法,通过 Tomcat 内置的 `CorsFilter` 实现全局支持。适用于静态文件(如 HTML、JS) Java Web 服务(如 Spring MVCSpring Boot)同时生效[^1][^3]。 1. **编辑 Tomcat 的 `web.xml` 文件**: - 文件路径:`{TOMCAT_HOME}/conf/web.xml`(Tomcat 全局配置)或 `{TOMCAT_HOME}/webapps/your-app/WEB-INF/web.xml`(特定应用配置)。 - 取消 `CorsFilter` 的注释,并配置参数: ```xml <filter> <filter-name>cross-origin</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> <init-param> <param-name>cors.allowed.origins</param-name> <param-value>*</param-value> <!-- 允许所有来源,可替换为具体名如 https://example.com --> </init-param> <init-param> <param-name>cors.allowed.methods</param-name> <param-value>GET,POST,PUT,DELETE,HEAD,OPTIONS</param-value> <!-- 允许的 HTTP 方法 --> </init-param> <init-param> <param-name>cors.allowed.headers</param-name> <param-value>*</param-value> <!-- 允许所有请求头 --> </init-param> </filter> <filter-mapping> <filter-name>cross-origin</filter-name> <url-pattern>/*</url-pattern> <!-- 匹配所有 URL --> </filter-mapping> ``` - **参数说明**: - `cors.allowed.origins`: 指定允许的来源(`*` 表示所有)。 - `cors.allowed.methods`: 包括 OPTIONS 方法,避免 403 错误(常见于预检请求)[^3]。 - 重启 Tomcat 后生效。 2. **验证配置**: - 使用浏览器开发者工具检查响应头是否包含 `Access-Control-Allow-Origin: *`。 - 如果遇到 OPTIONS 请求 403 错误,确保 `cors.allowed.methods` 包含 `OPTIONS`[^3]。 此方法简单高效,但灵活性较低,适用于所有部署在 Tomcat 的应用[^1][^3]。 #### 方法 2: 使用 Java Web 拦截器(适用于特定应用) 如果您的应用需要更细粒度的控制(如仅某些路径允许),可以在 Java Web 项目中实现一个拦截器。这适用于 Servlet 或 Spring MVC 应用[^4]。 1. **创建拦截器类**: - 在项目中添加一个类,实现 `HandlerInterceptor` 接口: ```java import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class CorsInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有来源 response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "*"); // 允许所有请求头 return true; // 继续处理请求 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 可选的后续处理 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 可选的完成处理 } } ``` 2. **注册拦截器**: -Spring MVC 配置文件中添加: ```xml <mvc:interceptors> <bean class="com.yourpackage.CorsInterceptor"/> </mvc:interceptors> ``` - 或使用 Java 配置Spring Boot): ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CorsInterceptor()); } } ``` - 重启应用后,拦截器会对所有请求生效。 此方法灵活,但需要代码修改,适合对特定路由进行定制[^4]。 #### 方法 3: 使用 Spring MVC 的自定义配置(适用于 Spring 应用) 对于 Spring Boot 或 Spring MVC 项目,可以通过 `CorsConfigurationSource` 实现动态配置,例如只允许 `/api` 路径[^2]。 1. **创建自定义 CORS 配置类**: ```java import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import javax.servlet.http.HttpServletRequest; import java.util.Collections; @Configuration public class CustomCorsConfig implements CorsConfigurationSource { @Override public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { CorsConfiguration config = new CorsConfiguration(); // 仅对 /api 路径启用 if (request.getRequestURI().startsWith("/api")) { config.setAllowedOrigins(Collections.singletonList("https://example.com")); // 指定允许的来源 config.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS")); config.setAllowedHeaders(Collections.singletonList("*")); } else { return null; // 其他路径不处理 } return config; } } ``` 2. **启用配置**: -Spring Boot 主类中添加: ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` - Spring 会自动检测 `CorsConfigurationSource` Bean。 此方法最灵活,支持基于请求路径的动态规则,适合复杂应用[^2]。 #### 注意事项 - **OPTIONS 请求处理**:预检请求(OPTIONS 方法)必须被允许,否则会导致 403 错误。确保配置中包含 `OPTIONS` 方法[^3]。 - **安全性**:避免使用 `*` 作为 `allowed.origins`,在生产环境中应指定具体名。 - **测试**:使用 Postman 或浏览器控制台检查响应头,确认 `Access-Control-Allow-Origin` 等头信息存在。 - **性能**:全局 CorsFilter 可能引入轻微开销,但通常可忽略。 通过以上方法,您可以有效解决 Tomcat 中的问题。选择方法时,考虑您的应用架构:方法 1 适合纯 Tomcat 环境,方法 2 3 适合 Spring 集成场景[^1][^2][^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值