当前位置: 首页 > news >正文

SpringBoot工具库:解决SpringBoot2.*版本跨域问题

1.解决问题:When allowCredentials is true, xxxxxxx , using “allowedOriginPatterns“ instead

2.3版本跨域配置如下

/*** 跨域问题解决*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("*").allowedMethods("*").allowedHeaders("*").maxAge(3600).allowCredentials(true);}
}

1.1.解决方法:

        Spring官网有类似问题:https://github.com/spring-projects/spring-framework/issues/26111

        大致意思为:提供了allowedOriginPatterns方法供使用。原本的allowCredentials为true时,allowedOrigins不能使用 * 号匹配

/*** 跨域问题解决*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOriginPatterns("*").allowedMethods("*").allowedHeaders("*").maxAge(3600).allowCredentials(true);}
}

其实解决跨域大分类有2种方式,一种是利用注解,一种写个配置类 

2.解决跨域的几种方式

2.1.CorsFilter 方式设置跨域

        CorsFilter过滤器:通过Spring Boot的CORS过滤器来处理跨域请求,需要定义一个CorsFilter Bean,例如:

@Configuration
public class CoreFilter {@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration config = new CorsConfiguration();config.addAllowedOriginPattern("*");  // 不是 addAllowedOriginconfig.setAllowCredentials(true);config.addAllowedHeader("*");config.addAllowedMethod("*");source.registerCorsConfiguration("/**", config);FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));bean.setOrder(Ordered.HIGHEST_PRECEDENCE);return new CorsFilter(source);}
}

2.2.拦截器实现跨域

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.Serializable;@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer, Serializable {private static final long serialVersionUID = 1L;@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")// 不是 addAllowedOrigin.allowedOriginPatterns("*").allowedMethods("*").allowedHeaders("*").maxAge(3600).allowCredentials(true);}/*** 修改访问路径* @param configurer*/public void configurePathMatch(PathMatchConfigurer configurer) {// 设置为true后,访问路径后加/ 也能正常访问  /user == /user/configurer.setUseTrailingSlashMatch(true);}}

        与使用 CorsFilter 方式一样,当 allowCredentials 为 true时,不可以将 allowedOrigins 设置为 *,必须用 allowedOriginPatterns。否则最终也会到 CorsConfiguration#validateAllowCredentials 方法中的校验。

2.3.通过 @CrossOrigin 实现跨域

@CrossOrigin 可以标注类和单个方法。使用@CrossOrigin注解标注在Controller类或方法上,指定允许跨域的源地址、请求方法、Header等属性

标注类:

该 Controller 请求路径下的所有方法都允许跨域。

@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {@RequestMapping(method = RequestMethod.GET, path = "/{id}")public Account retrieve(@PathVariable Long id) {// ...}@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")public void remove(@PathVariable Long id) {// ...}
}

        在类级别上添加了 @CrossOrigin。因此,retrieve() 和 remove() 方法都启用了 @CrossOrigin。我们可以通过指定以下注解属性的值来自定义配置:originsmethodsallowedHeadersexposedHeadersallowCredentials 或 maxAge

标注方法:

仅标注的方法允许跨域。

@RestController
@RequestMapping("/account")
public class AccountController {@CrossOrigin@RequestMapping(method = RequestMethod.GET, path = "/{id}")public Account retrieve(@PathVariable Long id) {// ...}@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")public void remove(@PathVariable Long id) {// ...}
}

在上面的示例中,我们只为 retrieve() 方法启用了 CORS。我们可以看到,我们没有为 @CrossOrigin 注解设置任何配置,因此它使用的是默认值:

  • 允许所有 origin。
  • 允许使用的 HTTP 方法是 @RequestMapping 注解(本例中为 GET)中指定的方法。
  • 缓存预检响应的时间(maxAge)为 30 分钟。

在类上和方法上

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {@CrossOrigin("http://example.com")@RequestMapping(method = RequestMethod.GET, "/{id}")public Account retrieve(@PathVariable Long id) {// ...}@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")public void remove(@PathVariable Long id) {// ...}
}

Spring 将合并两个注解的属性,创建合并的 CORS 配置。

这里,两个方法的 maxAge 都是 3600 秒,remove() 方法允许所有 origin,而 retrieve() 方法只允许来自 http://example.com 的 origin。

2.4.nginx

Nginx反向代理:将请求转发给Nginx,由Nginx统一处理跨域请求,例如:

location /api/ {add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';if ($request_method = 'OPTIONS') {add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain; charset=utf-8';add_header 'Content-Length' 0;return 204;}proxy_pass http://localhost:8080;
}

2.5.webFilter

使用@WebFilter注解:该注解可以直接在过滤器类上使用,并指定过滤的url,类似于xml文件中配置的filter

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;@Component
@WebFilter(urlPatterns = "/*")
@Order(-99999)
public class CorsFilter extends HttpFilter {private static final long serialVersionUID = 2386571986045107652L;private static final String OPTIONS_METHOD = "OPTIONS";@Overrideprotected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {String origin = req.getHeader(HttpHeaders.ORIGIN);if (!StringUtils.isEmpty(origin)) {// 允许客户端的域res.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);// 允许客户端提交的HeaderString requestHeaders = req.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);if (!StringUtils.isEmpty(requestHeaders)) {res.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders);}// 允许客户端访问的Headerres.addHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");// 允许客户端携带凭证信息res.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");// 允许客户端请求方法res.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, OPTIONS, DELETE");if (OPTIONS_METHOD.equalsIgnoreCase(req.getMethod())) {res.setStatus(HttpServletResponse.SC_NO_CONTENT);res.setContentType(MediaType.TEXT_HTML_VALUE);res.setCharacterEncoding("utf-8");res.setContentLength(0);res.addHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800");return;}}super.doFilter(req, res, chain);}
}
http://www.lryc.cn/news/159683.html

相关文章:

  • docker安装开发常用软件MySQL,Redis,rabbitMQ
  • C# Unity FSM 状态机
  • pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速
  • 【精读Uboot】SPL阶段的board_init_r详细分析
  • canvas绘制渐变色三角形金字塔
  • 企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
  • Debain JDK8 安装
  • Python序列操作指南:列表、字符串和元组的基本用法和操作
  • 【已更新代码图表】2023数学建模国赛E题python代码--黄河水沙监测数据分析
  • 【前端】CSS-Grid网格布局
  • 计算机竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别
  • 2023-9-8 求组合数(二)
  • k8s service的一些特性
  • C++中std::enable_if和SFINAE介绍
  • 华为OD机考算法题:数字加减游戏
  • WPF命令
  • Unity中Shader的屏幕抓取 GrabPass
  • 手撕 队列
  • 【autodl/linux配环境心得:conda/本地配cuda,cudnn及pytorch心得】-未完成
  • macOS Ventura 13.5.2(22G91)发布,附黑/白苹果镜像下载地址
  • vue 子组件向父组件传递参数 子传父
  • 自然语言处理学习笔记(八)———— 准确率
  • Matlab 如何选择窗函数和 FFT 的长度
  • node.js下载安装环境配置以及快速使用
  • 使用栈检查括号的合法性 C 实现
  • 小白备战大厂算法笔试(四)——哈希表
  • 云原生Kubernetes:pod基础
  • Ansys Zemax | 手机镜头设计 - 第 3 部分:使用 STAR 模块和 ZOS-API 进行 STOP 分析
  • CSP-J初赛复习大题整理笔记
  • 面试题 ⑤