详解springboot解决CORS跨域的三种方式

目录
  • 一、实现WebMvcConfigurer接口
  • 二、实现filter过滤器方式
  • 三、注解@CrossOrigin
  • 四、实战
  • 五、cookie的跨域

一、实现WebMvcConfigurer接口

@Configuration
public class WebConfig implements WebMvcConfigurer {
    /**
     * 添加跨域支持
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 允许跨域访问的路径  '/**'表示应用的所有方法
        registry.addMapping("/**")
            // 允许跨域访问的来源 '*'表示所有域名来源
            .allowedOriginPatterns("*")
            // .allowedOrigins("*") // 允许跨域访问的来源 SpringBoot2.4.0之前的版本
            // 允许跨域请求的方法  '*'表示所有
            .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
            // 是否允许发送cookie true-允许 false-不允许 默认false。对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,这个值只能设为true
            .allowCredentials(true)
            // 预检间隔时间1小时,单位为秒。指定本次预检请求的有效期,在有效期间,不用发出另一条预检请求。
            // 浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段
            // 浏览器发出CORS非简单请求,会在正式通信之前,增加一次OPTIONS查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
            .maxAge(3600)
            // 允许跨域请求可携带的header,'*'表所有header头。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定
            .allowedHeaders("*");
    }
}

二、实现filter过滤器方式

@WebFilter
@Configuration
public class CorsFilter implements Filter {
    @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-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

三、注解@CrossOrigin

@CrossOrigin(originPatterns = "*", allowCredentials = "true")

@CrossOrigin可配置在方法上,也可配置在类上。

四、实战

创建两个普通的SpringBoot项目A、B,A配置8081端口,B配置8082端口。

在A的resources/static目录下创建一个html文件index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<!-- jquery库可百度jquery cdn -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
    function btnClick() {
        $.get('http://localhost:8082/hello/hello', function (msg) {
            $("#app").html(msg);
        });
    }

    function btnClick2() {
        $.post('http://localhost:8082/hello/hello', function (msg) {
            $("#app").html(msg);
        });
    }
</script>

<body>

<div id="app"></div>
<input type="button" onclick="btnClick()" value="get_button">
<input type="button" onclick="btnClick2()" value="post_button">

</body>
</html>

B提供2个web接口:

@RestController
@RequestMapping("/hello")
public class HelloController {
    // @CrossOrigin(originPatterns = "*", allowCredentials = "true")
    @GetMapping("/hello")
    public String hello() {
        System.out.println("get hello");
        return "get hello";
    }

    // @CrossOrigin(originPatterns = "*", allowCredentials = "true")
    @PostMapping("/hello")
    public String hello2() {
        System.out.println("post hello");
        return "post hello";
    }
}

分别启动A、B服务,浏览器访问A的index.html,点击按钮,浏览器控制台报错如下:http://localhost:8081/index.html

Access to XMLHttpRequest at 'http://localhost:8082/hello/hello' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

为B项目使用方式一,添加跨域支持,重启,再次点击按钮,可正常访问,观察响应头多了支持跨域的信息:

五、cookie的跨域

从Chrome51开始,浏览器cookie添加了一个新属性SameSite,以防止 CSRF 攻击和用户跟踪。

SameSite可取值:Strict、Lax、None。

Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。导航到目标 URL 的 GET 请求仅包括三种情况:链接、预加载请求和 GET 表单。

网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

SpringBoot 2.6及以上版本

网上查到可使用配置(但亲测无效!):

server.servlet.session.cookie.same-site=none
server.servlet.session.cookie.secure=true

SpringBoot 2.6以下版本

如果使用 Tomcat 作为服务器,则可以通过以下配置设置会话 cookie 的 SameSite 属性(亲测无效!)。

server.servlet.session.cookie.secure=true
@Configuration
public class TomcatCookieConfig {
    @Bean
    public TomcatContextCustomizer sameSiteCookiesConfig() {
        return context -> {
            final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
            // SameSite
            cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
            context.setCookieProcessor(cookieProcessor);
        };
    }
}

如果您使用的是 Spring-Session,那么您可以使用以下配置来设置 cookie 的 SameSite 属性。

        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-core</artifactId>
        </dependency>
@Configuration
public class SpringSessionConfiguration {
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        // Strict-严格模式 Lax-松懈模式 None-无
        cookieSerializer.setSameSite("None");
        cookieSerializer.setUseSecureCookie(true);
        return cookieSerializer;
    }
}

自己的解决方式

@Configuration
public class CookieConfig {
    private static String domain;

    @Value("${domain}")
    public void setDomain(String domain) {
        CookieConfig.domain = domain;
    }

    public static HttpCookie generateHttpCookie(String name, String value) {
        return ResponseCookie.from(name, value)
            .domain(domain)
            // cookie跨域设置
            .sameSite("None")
            // 在https下传输,配合sameSite=None使用
            .secure(true)
            .path("/")
            // 有效期24小时
            .maxAge(60 * 60 * 24)
            .build();
    }
}
    @GetMapping("/hello")
    public String hello(HttpServletResponse response) {
        HttpCookie cookie2 = CookieConfig.generateHttpCookie("age", "18");
        response.addHeader(HttpHeaders.SET_COOKIE, cookie2.toString());
        HttpCookie cookie3 = CookieConfig.generateHttpCookie("id", "77");
        response.addHeader(HttpHeaders.SET_COOKIE, cookie3.toString());
        System.out.println("get hello");
        return "get hello";
    }

参考:https://www.cnblogs.com/javastack/p/14255114.html

到此这篇关于详解springboot解决CORS跨域的三种方式的文章就介绍到这了,更多相关springboot CORS跨域内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Springboot处理配置CORS跨域请求时碰到的坑

    最近开发过程中遇到了一个问题,之前没有太注意,这里记录一下.我用的SpringBoot版本是2.0.5,在跟前端联调的时候,有个请求因为用户权限不够就被拦截器拦截了,拦截器拦截之后打印日志然后response了一个错误返回了,但是前端Vue.js一直报如下跨域的错误,但是我是配置了跨域的. has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested res

  • SpringBoot开发技巧之如何处理跨域请求CORS

    目录 SpringBoot处理跨域 特殊情况 解决方法 自定义Cors过滤器 通过配置类指定过滤器的优先级 在前后分离的架构下,我们经常会遇到跨域CORS问题,在浏览器上的表现就是出现如下一段错误提示: No 'Access-Control-Allow-Origin' header is present on the requested resource. 下面看一下如何让你的SpringBoot项目支持CORS跨域. SpringBoot处理跨域 在SpringBoot后端处理跨域比较简单,只

  • springboot跨域CORS处理代码解析

    这篇文章主要介绍了springboot跨域CORS处理代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 源(Origin) 源指URL的协议,域名,端口三部分组成,如果这个三个成分都相同,就判定是同源,否则为不同源. 同源策略(Same origin policy)是一种浏览器的约定,即在浏览器中禁止非同源访问. 二 CORS CORS即"跨域资源共享"(Cross-origin resource sharing),是一个W

  • Springboot跨域CORS处理实现原理

    一 源(Origin) 源指URL的协议,域名,端口三部分组成,如果这个三个成分都相同,就判定是同源,否则为不同源. 同源策略(Same origin policy)是一种浏览器的约定,即在浏览器中禁止非同源访问. 二 CORS CORS即"跨域资源共享"(Cross-origin resource sharing),是一个W3C标准.它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了ajax只能同源使用的限制.springboot也提供了cors的解决方法.

  • vue+springboot实现项目的CORS跨域请求

    跨域资源共享CORS(Cross-origin Resource Sharing),是W3C的一个标准,允许浏览器向跨源的服务器发起XMLHttpRequest请求,克服ajax请求只能同源使用的限制.关于CORS的详细解读,可参考阮一峰大神的博客:跨域资源共享CORS详解.本文为通过一个小demo对该博客中分析内容的一些验证. 1.springboot+vue项目的构建和启动 细节不在此赘述,任何简单的springboot项目就可以,而前端vue项目只需用axios发ajax请求即可. 我的d

  • springboot中如何通过cors协议解决跨域问题

    1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可能第一个想到的解决方案就是jsonp,并且以前处理跨域问题我基本也是这么处理. 但是jsonp方式也同样有不足,不管是对于前端还是后端来说,写法与我们平常的ajax写法不同,同样后端也需要作出相应的更改.并且,jsonp方式只能通过get请求方式来传递参数,当然也还有其它的不足之处,针对于此,我并没有急着使用jsonp的方式来解决跨域问题,去网上找寻其它方式,也就是本文主

  • 基于SpringBoot解决CORS跨域的问题(@CrossOrigin)

    一.关于跨域介绍 在前后分离的架构下,跨域问题难免会遇见比如,站点 http://domain-a.com 的某 HTML 页面通过 的 src 请求 http://domain-b.com/image.jpg. 网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源. 出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求. 例如,XMLHttpRequest和Fetch API遵循同源策略. 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非

  • Springboot处理CORS跨域请求的三种方法

    前言 Springboot跨域问题,是当前主流web开发人员都绕不开的难题.但我们首先要明确以下几点 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了. 之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议.域名.端口号都完全一致. 浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的H

  • SpringBoot跨域Jsonp和Cors的方法

    有一次我的项目中采用了前后端分离的模式,引起了跨域问题,本文将介绍我所采用的跨域解决方法. 首先要了解产生跨域的本质,也就是同源策略的限制,源是指域名.端口号.协议,有一者不相同将被浏览器拒绝接受响应信息,(请求可以发送出去,但是浏览器不接受响应). 解决方法: 1. jsonp jsonp的原理的 src="" 属性不受同源策略的限制,动态创建一个callback回调函数,服务器调用回调函数把数据放进去,具体的细节打算以后做一个专门讲解. 这里给一个模版: $.ajax({ type

  • 详解springboot设置cors跨域请求的两种方式

    1.第一种: public class CorsFilter extends OncePerRequestFilter { static final String ORIGIN = "Origin"; protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOE

随机推荐