Spring Boot 对 跨源(域)资源共享 的支持(CORS)

本文详细介绍了CORS(跨源资源共享)的概念及其在SpringBoot中的应用。通过实例展示了如何使用@CrossOrigin注解处理跨域请求,包括简单请求和预检请求。同时,还演示了当请求头发生变化时,CORS策略如何阻止请求。最后,讲解了如何在SpringBoot中设置全局CORS配置,以允许特定域名的跨域请求。
摘要由CSDN通过智能技术生成

Spring Boot 对跨源(域)资源共享的支持(CORS)

首先,什么是跨域资源?

跨源资源共享(CORS) (或通俗地译为跨域资源共享) 是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他 origin(域,协议,端口),这样浏览器就可以访问加载这些资源。跨源资源共享还通过一种机制来检查服务器是否辉允许要发送的真是请求,该机制通过浏览器发起一个服务器托管的跨源资源的预检请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。

例子: 运行在 http://domain-a.com 的JavaScript代码使用XMLHttpRequest来发起一个到https://domain-b.com/data.json 的请求。

Spring Boot 对 CORS 的介绍:是一个由大多数浏览器实现的 W3C 规范,它允许你以一种灵活的方式指定哪种跨域请求是合法的,而不是使用一些不那么安全和强大的方法,如 IFRAME 或 JSONP。

专业解释,强烈推荐阅读!!!
关于CORS 更详细的介绍请参考 MDN 跨源资源共享(CORS)

跨域请求错误以什么形式出现呢?

演示:此 testCrossOrigin.html位于 http://localhost:8080域下

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script>
            var invocation = new XMLHttpRequest();
            var url = 'http://localhost:8333/testCrossOrigin';
            // 简单请求
            function callOtherDomain(append) {
                if (invocation) {
                    invocation.open('GET', url+append, true);
                    invocation.onloadend = () => {
                        console.log(invocation.responseText);
                        document.write(invocation.responseText);
                    };
                    invocation.send();
                }
            }
        </script>
    </head>
    <body>
        <button onclick="callOtherDomain('')">testCrossOrigin</button>
    </body>
</html>

为了模拟跨域, 在http://localhost:8333 域下创建 testCrossOrigin Controller

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestCrossOriginController {
	@ResponseBody
	@RequestMapping("/testCrossOrigin")
	public String testCrossOrigin() {
		String s = "ok";
		return s;
	}
}

在浏览器中打开 http://localhost:8080/testCrossOrigin.html 点击testCrossOrigin 按钮

在这里插入图片描述

出现错误信息:
在这里插入图片描述

可以看到 请求已被CORS策略阻止

Access to XMLHttpRequest at 'http://localhost:8333/testCrossOrigin' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Spring Boot 添加对跨域的支持

Spring Boot 中使用 @CrossOrigin 注解支持 CORS

修改上例 TestCrossOriginController类,添加@CrossOrigin(originPatterns = "http://localhost:8080")

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@CrossOrigin(originPatterns = "http://localhost:8080")
public class TestCrossOriginController {
	@ResponseBody
	@RequestMapping("/testCrossOrigin")
	public String testCrossOrigin() {
		String s = "ok";
		return s;
	}
}

浏览器测试

在这里插入图片描述

ok~! 对于一个简单的跨域请求 已经ok。

预检请求

“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。即请求时向服务器发送自定义,或者 HTTP 规范请求头,以供服务器对此请求检查。

演示:

此 testCrossOrigin.html位于 http://localhost:8080域下

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script>
            var invocation = new XMLHttpRequest();
            var url = 'http://localhost:8333/testCrossOriginPreInspection';
            var body = '<?xml version="1.0"?><person><name>Arun</name></person>';
            // 预检请求
            function callOtherDomain(){
                if(invocation)
                {
                    invocation.open('POST', url, true);
                    invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
                    invocation.setRequestHeader('Content-Type', 'application/xml');
                    invocation.onloadend = () => {
                        console.log(invocation.responseText);
                        document.write(invocation.responseText);
                    };
                    invocation.send(body);
                }
            }
        </script>
    </head>
    <body>
        <button onclick="callOtherDomain()">testCrossOrigin</button>
    </body>
</html>

http://localhost:8333 域下创建 testCrossOrigin Controller

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@CrossOrigin(originPatterns = "http://localhost:8080")
public class TestCrossOriginController {

	@CrossOrigin(originPatterns = "http://localhost:8080", allowedHeaders = {"X-PINGOTHER", "Content-Type"},
			methods = {RequestMethod.GET,RequestMethod.POST,RequestMethod.OPTIONS})
	@RequestMapping("/testCrossOriginPreInspection")
	public String testCrossOriginPreInspection(HttpServletRequest request,@RequestBody String requestBody) {
		request.setAttribute("requestBody",requestBody);
		return "formCrossOrigin";
	}
}

浏览器测试

在这里插入图片描述

在这里插入图片描述

服务器可以接收到请求时的数据,并且执行了响应的Controller。

而当我们对 testCrossOrigin.html 中 script 中 invocation 设置的请求头做出更改时

 invocation.setRequestHeader('X-PINGOTHER', 'pingpong');

修改

 invocation.setRequestHeader('X1-PINGOTHER', 'pingpong');

测试浏览器请求

在这里插入图片描述

受到了 CORS 策略的阻止

Spring Boot 添加全局 CORS
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration(proxyBeanMethods = false)
public class MyCorsConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**");
            }

        };
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值