SpringBoot中到底该如何解决跨域问题

目录
  • 前言
  • 1、跨域访问报错
  • 2、同源定义
  • 3、跨域问题如何解决?
  • 4、CORS原理
  • 5、SpringMVC中如何解决跨域问题?
  • 6、方案1:方法或者类上标注@CrossOrigin注解
  • 7、方案2:全局配置的方式
  • 8、方案3:拦截器的方式CorsFilter
  • 9、案例代码
    • 9.1、案例完整代码
    • 9.2、接口代码:CorsController
    • 9.3、静态页面:cors.html
    • 9.4、将chat21-cores模块发布到tomcat
    • 9.5、运行静态页面cors.html
    • 9.6、点击第1个按钮,测试跨域正常请求
    • 9.7、点击第2个按钮,测试跨域异常请求
  • 10、总结

前言

今天又给大家带来了一个很重要的知识点:SpringMVC中如何处理跨域问题,本文的内容同样适合于SpringBoot

1、跨域访问报错

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

出于安全原因,浏览器禁止Ajax调用驻留在当前原点之外的资源,比如从a.com发送一个ajax请求到b.com,则浏览器控制台会报跨域访问错误。

如下图,从http://localhost:63342/站点页面中向ttp://localhost:8080/chat21/cors/test2发送一个ajax请求,则出现了红色的错误信息,错误中包含了Access-Controll-Allow-Origin这样字样的错误,以后看到这个的时候,大家就要一眼看出来这是跨域问题。

2、同源定义

同源策略是浏览器的一个重要的安全策略,它用于限制一个源的文档或其加载的脚本如何与另外一个源进行交互,它能够隔绝恶意文档,减少被攻击的媒介。

如果两个URL的协议主机名端口号都是相同的,那么这两个URL就是同源的,否则不同源,不同源的访问就会出现跨域问题,就会出现上面的错误。

下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:

URL 结果 原因
http://store.company.com/dir2/other.html 同源 只有路径不同
https://store.company.com/secure.html 非同源 协议不同
http://store.company.com:81/dir/etc.html 非同源 端口号不同
http://news.company.com/dir/other.html 非同源 主机名不同

也就是说当在http://store.company.com/dir/page.html这个网站中向https://store.company.comhttp://store.company.com:81http://news.company.com三个地址发起AXJX请求都会失败并且会报跨域的错误。这就是浏览器的同源策略,只能访问同源的数据。

3、跨域问题如何解决?

跨域问题需要使用CORS来解决,请求端和后端接口需要遵循CORS规则来通信,便可解决跨域访问的问题。

CORS全称Cross-Origin Resource Sharing, 即跨域资源共享,是一个由一系列HTTP头组成的系统,这些HTTP头决定浏览器是否阻止前端javascript代码获取跨域请求的响应。为什么需要CORS ?这是因为浏览器存在同源安全策略,当我们在当前域请求另外一个域的资源时,浏览器默认会阻止脚本读取它的响应,这时CORS就有了用武之地。

跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如IFRAME或JSONP等。

4、CORS原理

CORS的原理:简单点说,就是在请求头或响应头中添加了一些配置,通过这些配置来便可轻松解决跨域问题。

想详细了解CORS原理的,建议先阅读下面2篇文章,然后再继续向下看,否则,最后你知道SpringMVC是如何解决的,但是不知道本质的原理是什么。

  • CORS通信:http://itsoku.com/article/197
  • 浏览器安全策略 & CORS:http://itsoku.com/article/198

5、SpringMVC中如何解决跨域问题?

SpringMVC内部提供了跨域问题的解决方案,只需要做一些简单的配置,而接口基本上不用做任何修改,便可解决跨域问题。

SpringMVC解决跨域问题的原理也就是SpringMVC遵循了CORS通信的规则来解决了跨域的问题,在响应头中添加了一些CORS需要的信息。

SpringMVC中提供了3种方案来解决跨域问题,下面一起来了解下。

6、方案1:方法或者类上标注@CrossOrigin注解

接口方法上标注org.springframework.web.bind.annotation.CrossOrigin注解,如下test1接口上标注了@CrossOrigin注解,这个接口就支持跨域访问,@CrossOrigin注解中含有更详细的配置,这里就不细说了

也可以在类上标注@CrossOrigin注解,那么这个类中所有接口会支持跨域访问

也可同时在类和方法上标注@CrossOrigin注解,最后方法上的跨域访问会取合并后的配置

@RestController
public class CorsController {

    @RequestMapping("/cors/test1")
    @CrossOrigin
    public List<String> test1() {
        List<String> result = Arrays.asList("www.itsoku.com",
                "Spring高手系列",
                "SpringMVC系列",
                "MySQL系列",
                "高并发系列");
        return result;
    }

}

7、方案2:全局配置的方式

除了细粒度、基于注释的配置之外,您还可能需要定义一些全局CORS配置,这类似于使用筛选器,但可以声明为Spring MVC并结合细粒度@CrossOrigin配置。默认情况下,所有origins and GET, HEAD and POST methods是允许的。

@EnableWebMvc
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {

        //每次调用registry.addMappin可以添加一个跨域配置,需要多个配置可以多次调用registry.addMapping
        registry.addMapping("/**")
                .allowedOrigins("*") //放行哪些原始域
                .allowedMethods("PUT", "DELETE","POST", "GET") //放行哪些请求方式
                .allowedHeaders("header1", "header2", "header3") //放行哪些原始请求头部信息
                .exposedHeaders("header1", "header2") //暴露哪些头部信息
                .allowCredentials(false) //是否发送 Cookie
                .maxAge(3600);

        // Add more mappings...
    }
}

8、方案3:拦截器的方式CorsFilter

//处理跨域的Filter
//1. 添加 CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送 Cookie
config.setAllowCredentials(false);
//放行哪些请求方式
config.addAllowedMethod("*");
//放行哪些原始请求头部信息
config.addAllowedHeader("*");
//暴露哪些头部信息
config.addExposedHeader("*");
//2. 添加映射路径
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**",config);

9、案例代码

9.1、案例完整代码

git地址:https://gitee.com/javacode2018/springmvc-series

9.2、接口代码:CorsController

CorsController中有2个接口,第一个接口上标注了@CrossOrigin注解,可以解决跨域访问的问题,而第二个方法没有标注。

@RestController
public class CorsController {

    @RequestMapping("/cors/test1")
    @CrossOrigin
    public List<String> test1() {
        List<String> result = Arrays.asList("www.itsoku.com",
                "Spring高手系列",
                "SpringMVC系列",
                "MySQL系列",
                "高并发系列");
        return result;
    }

    @RequestMapping("/cors/test2")
    public List<String> test2() {
        List<String> result = Arrays.asList("www.itsoku.com",
                "Spring高手系列",
                "SpringMVC系列",
                "MySQL系列",
                "高并发系列");
        return result;
    }

}

9.3、静态页面:cors.html

静态页面cors.html中添加了2个按钮,点击2个按钮的时候,分别以ajax跨域的方式访问上面2个接口,第1个按钮访问第一个接口,第2个按钮访问第二个接口,然后在浏览器控制台查看效果。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>cors</title>
    <script type="text/javascript" src="jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#cors-btn1").click(function () {
                $.ajax({
                    url: "http://localhost:8080/chat21/cors/test1",
                    success: function (data) {
                        console.log(JSON.stringify(data));
                    }
                });
            });
            $("#cors-btn2").click(function () {
                $.ajax({
                    url: "http://localhost:8080/chat21/cors/test2",
                    success: function (data) {
                        console.log(JSON.stringify(data));
                    }
                });
            });
        })
    </script>
</head>
<body>
<button id="cors-btn1">跨域测试test1</button>
<button id="cors-btn2">跨域测试test2</button>
</body>
</html>

9.4、将chat21-cores模块发布到tomcat

9.5、运行静态页面cors.html

在idea中选中cors.html,然后鼠标右键->Run,即可运行

运行效果如下(最好以chrome浏览器运行),idea中支持直接运行静态页面,大家注意这里的端口是63342,而上面tomcat的端口是8080,然后浏览器中按F12打开浏览器控制台,选中Console选项卡,稍后在这里可以看到点击按钮验证跨域的效果。

9.6、点击第1个按钮,测试跨域正常请求

再看看下面这个图,正常的跨域请求,响应头多了几个头,主要是Access-Control开头的头是和CORS相关的,浏览器就是根据这些响应头来决定跨域访问是不是正常的,如果没有这些头,浏览器将拒绝读取响应体,然后就报错啦。

9.7、点击第2个按钮,测试跨域异常请求

10、总结

掌握SpringMVC中解决跨域问题的3种方式

  1. 注解的方式:@CrossOrigin
  2. 全局配置的方式:WebMvcConfigurer接口的addCorsMappings方法中注册CORS配置
  3. 拦截器的方式:CorsFilter

到此这篇关于SpringBoot中到底该如何解决跨域问题的文章就介绍到这了,更多相关SpringBoot解决跨域问题内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Springboot跨域问题三种解决方案

    使用vue+axios+spring boot前后端分离项目时会出现跨域问题 解决方式: 一: 全局配置 /** * 就是注册的过程,注册Cors协议的内容. * 如: Cors协议支持哪些请求URL,支持哪些请求类型,请求时处理的超时时长是什么等. */ @Override public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**")// 所有的当前站点的请求地址,都支持跨域访问. .

  • springboot跨域问题解决方案

    这篇文章主要介绍了springboot跨域问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 springboot中的跨域问题,如果不注意的话,容易造成错误,本次springboot版本为2.13 前端错误信息: Access to XMLHttpRequest at 'http://localhost:8080/user/loginOn' from origin 'http://localhost:8082' has been blo

  • springboot后端解决跨域问题

    首先我门要知道什么是跨域: 跨域是指 不同域名之间相互访问.跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制. 也就是如果在A网站中,我们希望使用Ajax来获得B网站中的特定内容 如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题. 什么是同一个域? 同一协议,同一ip,同一端口,三同中有一不同就产生了跨域. 前端解决跨域: 前边也说了,跨域是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对Java

  • SpringBoot跨域问题的解决方法实例

    谈到跨域问题,首先我们要认识一下浏览器的同源策略 百度百科对同源策略的解释 当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面 当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的, 即检查是否同源,只有和百度同源的脚本才会被执行. [1] 如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问. 同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应

  • SpringBoot 跨域问题的解决方案

    什么是跨域? 定义:浏览器从一个域名的网页取请求另一个域名下的东西.通俗点说,浏览器直接从A域访问B域中的资源是不被允许的,如果想要访问,就需要进行一步操作,这操作就叫"跨域".例如,你从百度的页面,点击一个按钮,请求了新浪的一个接口,这就进行了跨域.不单单只有域名不同就是跨域,域名.端口.协议其一不同就是不同的域,请求资源需要跨域. 为什么要跨域? 为什么需要跨域,而不直接访问其他域下的资源呢?这是浏览器的限制,专业点说叫浏览器同源策略限制.主要是为了安全考虑.现在的安全框架,一般请

  • SpringBoot中到底该如何解决跨域问题

    目录 前言 1.跨域访问报错 2.同源定义 3.跨域问题如何解决? 4.CORS原理 5.SpringMVC中如何解决跨域问题? 6.方案1:方法或者类上标注@CrossOrigin注解 7.方案2:全局配置的方式 8.方案3:拦截器的方式CorsFilter 9.案例代码 9.1.案例完整代码 9.2.接口代码:CorsController 9.3.静态页面:cors.html 9.4.将chat21-cores模块发布到tomcat 9.5.运行静态页面cors.html 9.6.点击第1个

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

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

  • ASP.NET中Web API解决跨域问题

    一.什么是跨域问题 跨域:指的是浏览器不能执行其他网站的脚本.是由浏览器的同源策略造成的,是浏览器施加的安全限制.(服务端可以正常接收浏览器发生的请求,也可以正常返回,但是由于浏览器的安全策略,浏览器不能处理服务端的返回). 那么什么是同源策略呢? 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS.CSFR等攻击.所谓同源是指"协议+域名+端口"

  • VUE跨域详解以及常用解决跨域的方法

    目录 跨域 解决跨域常用方法: 一.VUE中常用proxy来解决跨域问题 二.JSONP解决跨域 三.CORS是跨域资源共享(Cross-Origin Resource Sharing),以 ajax 跨域请求资源,支持现代浏览器,IE支持10以上 四.iframe实现跨域 总结 跨域 当我们遇到请求后台接口遇到 Access-Control-Allow-Origin 时,那说明跨域了. 跨域是因为浏览器的同源策略所导致,同源策略(Same origin policy)是一种约定,它是浏览器最核

  • SpringBoot解决跨域请求拦截问题代码实例

    前言 同源策略:判断是否是同源的,主要看这三点,协议,ip,端口. 同源策略就是浏览器出于网站安全性的考虑,限制不同源之间的资源相互访问的一种政策. 比如在域名https://www.baidu.com下,脚本不能够访问https://www.sina.com源下的资源,否则将会被浏览器拦截. 注意两点: 1.必须是脚本请求,比如AJAX请求. 但是如下情况不会产生跨域拦截 <img src="xxx"/> <a href='xxx"> </a&

  • SpringBoot解决跨域的5种方式小结

    什么是跨域 跨域:指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制. 例如:a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源.注意:跨域限制访问,其实是浏览器的限制.理解这一点很重要!!! 同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域: java解决CORS跨域请求的方式 对于CORS的跨域请求,主

  • 教你用Java SpringBoot如何解决跨域

    目录 跨域 什么是跨域 CORS SpringBoot解决跨域方案 1.使用@CrossOrigin注解 2.Spring框架全局配置CORS配置 具体实现 1.使用@CrossOrigin注解 1.1目录结构 1.2运行结果 2.使用@CrossOrigin注解 2.1Spring MVC CORS 使用WebMvcConfigurerAdapter配置! 2.3Spring Boot CORS 使用WebMvcConfigurer配置 2.4CORS 使用Spring Security配置

  • 最新springboot解决跨域的几种方式小结

    目录 什么是跨域 springboot解决跨域的几种方式 方法一.SpringBoot的注解@CrossOrigin 方式二:使用CorsFilter 方式三:自定义过滤(web  filter)的方式 方式四:实现WebMvcConfigurer中addCorsMappings方法 方法五:采用nginx做动态代理 什么是跨域 跨域:指的是浏览器不能执⾏其他⽹站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制.例如:a页⾯想获取b页⾯资源,如果a.b页⾯的协议

  • SpringBoot前后端分离解决跨域问题的3种解决方案总结

    目录 什么是跨域 跨域问题的解决策略 三种解决方法 总结 什么是跨域 想要知道什么是跨域的话,我们可以通过一个小案例简单了解一下跨域的概念:在项目代码编写的时候,我们将前端项目代码和后端的项目代码相分离开,一个运行在本地的8080端口一个运行在本地的8888端口,这也就是我们常说的前后端分离项目.现在使用前端的请求去调用后端的接口,就会产生以下的错误 Access to XMLHttpRequest at 'http://localhost:8888/请求名' from origin ‘http

随机推荐