关于跨域无效的问题及解决(java后端方案)

2025-06-11 04:50

本文主要是介绍关于跨域无效的问题及解决(java后端方案),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教...

通用后端跨域方法

1、@CrossOrigin 注解

在Spring Boot 中给我们提供了一个注解 @CrossOrigin 来实现跨域,这个注解可以实现方法级别的细粒度的跨域控制。

我们可以在类或者方添加该注解,如果在类上添加该注解,该类下的所有接口都可以通过跨域访问,如果在方法上添加注解,那么仅仅只限于加注解的方法可以访问。

@Slf4j
@RestController
@RequestMapping(value = AppPath.SERVICE_LOCATION_URL + "/appointment")
@Api(value = "AppointmentController",tags = "预约列表接口")
@CrossOrigin
public class AppointmentController {

    @Autowired
    private LiveAppointmentService appointmentService;
	
	@RequestMapping
    @ApiOperation(value = "预约列表分页查询", response = CsLiveAppointmentDTO.class)
    public jsonResult<PageInfo> getAppointmentList(AppointmentListDTO dto){
        log.info("getAppointmentList vo:{}", JSONUtil.toJsonStr(dto));
        PageInfo<CsLiveAppointmentDTO> appointmentList = appointmentService.getAppointmentList(dto);
        return JsonResult.success(appointmentList);
    }
}

@CrossOrigin 注解不生效问题

在Spring框架4.2版本后,Spring给出了注解的方式解决问题。

即在Controller控制器中,在Controller注解上方添加@CrossOrigin注解。

但是使用这种方式后也有可能仍然出现跨域问题,解决方案就是:

  • 在@RequestMapping注解中没有指定Get、Post方式,或者使用@GetMapping或者@Post Mapping
  • 在@CrossOrigin(methods = {RequestMethod.POST})指定方法
@Slf4j
@RestController
@RequestMapping(value = AppPath.SERVICE_LOCATION_URL + "/appointment")
@Api(value = "AppointmentController",tags = "预约列表接口")
@CrossOrigin
public class AppointmentController {

    @Autowired
    private LiveAppointmentService appointmentService;

    @ApiOperation(value = "预约列表分页查询", response = CsLiveAppointmentDTO.class)
    //@GetMapping("getList")
    @RequestMapping(method = RequestMethod.GET)
    public JsonResult<PageInfo> getAppointmentList(AppointmerskYWntListDTO dto){
        log.info("getAppointmentList vo:{}", JSONUtil.toJsonStr(dto));
        PageInfo<CsLiveAppointmentDTO> appointmentList = appointmentService.getAppointmentList(dto);
        return JsonResult.success(appointmentList);
    }
}

2、springboot2.0 实现WebMvcConfigurer 实现跨域

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST","GET","OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(false).maxAge(3600);
    }
 
}
 

3、过滤器实现跨域

@WebFilter(filterName = "CorsFilter")
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class CorsFilter implements Filter {

    @Value("${allow.headers:X-Requested-With,Authorization,Content-Type}")
    private String allowHeaders;

    @Value("${allow.origin:https://xxx.com}")
    private String allowOrigin;

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
//        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Origin", "http://xxx:9091");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH,OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", allowHeaders);
//        response.setHeader("Access-Control-Allow-Headers", "*");
        log.info("CorsFilter res {},{}", response.getHeader("Access-Control-Allow-Origin"), response.containsHeader("Access-Control-Allow-Origin"));
        chain.doFilter(req, res);
    }
}

跨域不生效问题 

(1)、@Order(Ordered.HIGHEST_PRECEDENCE)如果有登录拦截,要将跨域filter等级提升为最高优先级 

(2)、 response.setHeader(“Access-Control-Allow-Headers”, “");

  • Access-Control-Allow-Headers: * 在部分客户端上有兼容问题,MDN中介绍 Access-Control-Allow-Headers: * 有两重意思。
  • 一个是在服务端设置Access-Control-Allow-Credentials: true的时候这个 * 只会被客户端当做字符串 * (我们不希望的,会出错的)。
  • 另一个是没有这个设置则会被当做通配符(我们希望的,不会出错的)。
  • 猜测是客户端对于 * 的实现上有兼容性问题,所以建议不要这样设置,用到什么设置什么最好,例如:Access-Control-Allow-Headers: Content-Type,X-Requested-With,Authorization。 

(3)、 response.setHeader(“Access-Control-Allow-Origin”, "”)

//指定允许其他域名访问
‘Access-Control-Allow-Origin:http://172.80.0.206'//一般用法(,指定域,动态设置),3是因为不允许携带认证头和cookies
//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回

(4)、 response.setHeader(“Access-Control-Allow-Methods”, “POST, GET, PATCH,OPTIONS, DELETE, PUT”);OPTIONS 在预检请求复杂请求中也会使用到 

(5)、 如果有spring security结合使用需要添加该过滤器

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protectedjs void configure(HttpSecurity security) throws Exception {
        security.csrf().disable();
        security.headers().frameOptions().disable();
        //加入过滤器
        security.addFilterBefore(new CORSFwww.chinasem.cnilter(), 			             	UsernamePasswordAuthenticationFilter.class);
    }
}

4、定制化参数实现跨域

前面要么是*,实际需求是根据业务参数定制化

@WebFilter(filterName = "corsFilter", urlPatterns = "/*",
        initParams = {@WebInitParam(name = "allowOrigin", value = "*"),
                @WebInitParam(name = "allowMethods", value = "GET,POST,PUT,DELETE,OPTIONS"),
                @WebInitParam(name = "allowCredentials", value = "true"),
                @WebInitParam(name = "allowHeaders", value = "Content-Type,X-Token")})
public class CorsFilter implements Filter {
 
    private String allowOrigin;
    private String allowMethods;
    private String allowCredentials;
    private String allowHeaders;
    private String exposeHeaders;
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        allowOrigin = filterConfig.getInitParameter("allowOrigin");
        allowMethods = filterConfig.getInitParameter("allowMethods");
        allowCredentials = filterConfig.getInitParameter("allowCredentials");
        allowHeaders = filterConfig.getInitParameter("allowHeaders");
        exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (!StringUtils.isEmpty(allowOrigin)) {
            if(allowOrigin.equals("*")){
                // 设置哪个源可以访问
                response.setHeader("Access-Control-Allow-Origin", allowOrigin);
            }else{
                List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
                if (allowOriginList != null && allowOriginList.size() > 0) {
                    String currentOrigin = request.getHeader("Origin");
                    if (allowOriginList.contains(currentOrigin)) {
                        response.setHeader("Access-Control-Allow-Origin", currentOrigin);
                    }
                }
            }
        }
        if (!StringUtils.isEmpty(allowMethods)) {
            //设置哪个方法可以访问
            response.setHeader("Access-Control-Allow-Methods", allowMethods);
        }
        if (!StringUtils.isEmpty(allowCredentials)) {
            // 允许携带cookie
            response.setHeader("Access-Control-Allow-Credentials", allowCredentials);
        }
        if (!StringUtils.isEmpty(allowHeaders)) {
            // 允许携带哪个头
            response.setHeader("Access-Control-Allopythonw-Headers", allowHeaders);
        }
        if (!StringUtils.isEmpty(exposeHeaders)) {
            // 允许携带哪个头
            response.setHeader("Access-Control-Expose-Headers", exposeHeaders);
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}

5、 使用SpringCloud网关GateWay实现跨域

原理和前面类似

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 CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(Boolean.TRUE);//允许Cookie跨域
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");//不要设置成*,参考前面

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

:在下层服务不需要在做任何跨域配置,例如注解@CrossOrigin,否则会由于配置冲突导致依然出现跨域问题

6、nginx配置代理解决跨域问题

server {
        listen       8000;
        server_name  localhost;
        # / 表示匹配路径为/的url
        location / {
           proxy_pass http://需要跨域的域名:5500;
        }
 
        # /user 表示访问以/user 开头 的地址 如/username,/user/find等
        location /user {
           proxy_pass http://需要跨域的域名:3000;
        }
 
    }

7、nginx配置响应头允许跨域

#
# Wide-open CORS config for nginx
#
location / {
	
	#### 对OPTIONS请求,会设置很多的请求头,并返回204
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
  javascript      #
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

这篇关于关于跨域无效的问题及解决(java后端方案)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2