Spring Boot 2.X 如何优雅的解决跨域问题?

一、什么是源和跨域

源(origin)就是协议、域名和端口号。
URL 由协议、域名、端口和路径组成,如果两个 URL 的协议、域名和端口全部相同,则表示他们同源。否则,只要协议、域名、端口有任何一个不同,就是跨域。

对 https://www.baidu.com/index.html 进行跨域比较:
URL是否跨域原因
https://www.baidu.com/more/index.html 不跨域 三要素相同
https://map.baidu.com/ 跨域 域名不同
http://www.baidu.com/index.html 跨域 协议不同
https://www.baidu.com:81/index.html 跨域 端口号不同

二、什么是同源策略?

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略又分为以下两种:

  1. DOM 同源策略:禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
  2. XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。

三、Spring Boot 跨域解决方案

本例使用 Spring Boot 2.1.2.RELEASE 演示,分别用 8080 和 8081 端口启动,部分代码如下:

跨域页面:testOtherDomain.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不同域名 -Java 碎碎念</title>
</head>
<body>
<button id="b1">点我测试</button>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
    $("#b1").click(function () {
        $.ajax({
            url: "http://localhost:8081/hello",
            type: "post",
            success:function (res) {console.log(res);
            }
        })});
</script>
</body>
</html>

接口类:HelloController

package com.example.helloSpringBoot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
@RequestMapping(
"/hello")
public String HelloSpring (){
return "hello Java 碎碎念!";
}
}

 未解决跨域前运行截图:

 

在 Spring Boot 2.X 应用程序中可以使用注解 @CrossOrigin,也可以通过使用 WebMvcConfigurer 对象来定义全局 CORS 配置。

  1. @CrossOrigin 注解示例代码
package com.example.helloSpringBoot.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@CrossOrigin
@RequestMapping(</span>"/hello"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String HelloSpring (){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "hello Java碎碎念!"<span style="color: rgba(0, 0, 0, 1)">;
}

}

  2. WebMvcConfigurer 对象示例代码

package com.example.helloSpringBoot.config;

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
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping(
"/")
.allowedOrigins(
"
")
.allowCredentials(
true)
.allowedMethods(
"GET", "POST", "DELETE", "PUT","PATCH")
.maxAge(
3600);
}
};
}
}

 

按照上面两种方式的一种配置完成后,即可实现对跨域的支持,运行成功截图如下:

 

完整源码地址:https://github.com/suisui2019/helloSpringBoot

推荐阅读

1.Redis Cluster 搭建高可用 Redis 服务器集群
2. 为什么单线程的 Redis 这么快?
3.Spring Boot 集成 spring session 实现 session 共享
4.Spring Boot 入门 - 快速搭建 web 项目
5.Spring Boot2.0 整合 Redis
6. 一篇文章搞定 SpringMVC 参数绑定


限时领取免费 Java 相关资料,涵盖了 Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink 等高并发分布式、大数据、机器学习等技术。
关注下方公众号即可免费领取: