一、跨域背景

1.1 何为跨域?

Url的一般格式:

协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址

示例:

https://www.dustyblog.cn:8080/say/Hello 是由

https + www + dustyblog.cn + 8080 + say/Hello 组成

组成。

只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。

1.2 一次正常的请求

  • Controller层代码:
 @RequestMapping("/demo")
@RestController
public class CorsTestController { @GetMapping("/sayHello")
public String sayHello() {
return "hello world !";
}
}
  • 启动项目,测试请求

浏览器打开localhost:8080/demo/sayHello

可以打印出“hello world”

1.3 跨域测试

以Chrome为例:

  • 打开任意网站,如:https://blog.csdn.net

  • 按F12,打开【开发者工具】,在里面的【Console】可以直接输入js代码测试;

var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/demo/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
var xhr = e.target;
console.log(xhr.responseText);
}

该结果表明:该请求在https://blog.csdn.net域名下请求失败!

二、解决方案 - Cors跨域

2.1 Cors是什么

CORS全称为Cross Origin Resource Sharing(跨域资源共享), 每一个页面需要返回一个名为Access-Control-Allow-Origin的http头来允许外域的站点访问,你可以仅仅暴露有限的资源和有限的外域站点访问。

我们可以理解为:如果一个请求需要允许跨域访问,则需要在http头中设置

Access-Control-Allow-Origin来决定需要允许哪些站点来访问。如假设需要允许https://www.dustyblog.c这个站点的请求跨域,则可以设置:

Access-Control-Allow-Origin:https://www.dustyblog.cn。

2.2 如何解决Cors跨域

2.2.1方案一:使用@CrossOrigin注解

Controller上使用@CrossOrigin注解,该类下的所有接口都可以通过跨域访问

 @RequestMapping("/demo2")
@RestController
//@CrossOrigin //所有域名均可访问该类下所有接口
@CrossOrigin("https://blog.csdn.net") // 只有指定域名可以访问该类下所有接口
public class CorsTest2Controller { @GetMapping("/sayHello")
public String sayHello() {
return "hello world --- 2";
}
}

这里指定当前的CorsTest2Controller中所有的方法可以处理https://csdn.net域上的请求,这里可以测试一下:

  • https://blog.csdn.net页面打开调试窗口,输入(注意:这里请求地址是/demo2,请区别于1.2 案例中的/demo)
var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/demo2/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
var xhr = e.target;
console.log(xhr.responseText);
}

返回结果:

ƒ (e) {
var xhr = e.target;
console.log(xhr.responseText);
}
VM156:8 hello world --- 2

说明跨域成功!

  • 换个域名测试一下看跨域是否还有效,在https://www.baidu.com按照上述方法测试一下,返回结果:
OPTIONS http://127.0.0.1:8080/demo2/sayHello 403
(anonymous)
Access to XMLHttpRequest at 'http://127.0.0.1:8080/demo2/sayHello'
from origin 'http://www.cnblogs.com' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

说明跨域失败!证明该方案成功指定了部分域名能跨域!

2.2.2方案二: CORS全局配置-实现WebMvcConfigurer

  • 新建跨域配置类:CorsConfig.java:
 /**
* 跨域配置
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer { @Bean
public WebMvcConfigurer corsConfigurer()
{
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
allowedOrigins("https://www.dustyblog.cn"). //允许跨域的域名,可以用*表示允许任何域名使用
allowedMethods("*"). //允许任何方法(post、get等)
allowedHeaders("*"). //允许任何请求头
allowCredentials(true). //带上cookie信息
exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
}
};
}
}
  • 测试,在允许访问的域名https://www.dustyblog.cn/控制台输入(注意,这里请求的是http://127.0.0.1:8080/demo3):
var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/demo3/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
var xhr = e.target;
console.log(xhr.responseText);
}

返回结果:

ƒ (e) {
var xhr = e.target;
console.log(xhr.responseText);
}
VM433:8 hello world --- 3

说明跨域成功,换个网址如https://www.baidu.com测试依旧出现需要跨域的错误提示,证明该配置正确,该方案测试通过。

2.2.3方案三:拦截器Filter实现

通过实现Fiter接口在请求中添加一些Header来解决跨域的问题

 @Component
public class CorsFilter implements Filter { @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
response.getWriter().println("ok");
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}

至此,跨域请求就完成了,有更多更好方法的朋友欢迎留言!

好文转转学习自:https://www.cnblogs.com/vandusty/p/11408422.html

SpringBoot:CORS处理跨域请求的三种方式的更多相关文章

  1. System.Web.Http.Cors配置跨域访问的两种方式

    System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心 ...

  2. django-Ajax发送POST请求(csrf跨站请求的三种方式),文件的上传

    第一种 <script> $(".eq").on("click",function () { $.ajax({ url:"/eq/&quo ...

  3. django-Ajax发送POST请求-csrf跨站请求的三种方式

    第一种 <script> $(".eq").on("click",function () { $.ajax({ url:"/eq/&quo ...

  4. jQuery 跨域访问的三种方式 No 'Access-Control-Allow-Origin' header is present on the reque

    问题: XMLHttpRequest cannot load http://v.xxx.com. No 'Access-Control-Allow-Origin' header is present ...

  5. Django使用jsonp和cors解决跨域请求问题

    1.使用jsonp的方式解决跨域请求的问题 我启动两个django项目,然后使用的端口不一样,在项目1中通过ajax发请求给项目2,然后接受项目2发送过来的数据 先看项目1的ajax的代码 $(&qu ...

  6. SpringBoot配置Cors解决跨域请求问题

    一.同源策略简介 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 什么是源 源[or ...

  7. SpringBoot设置支持跨域请求

    跨域:现代浏览器出全的考虑,在http/https请求时必须遵守同源策略,否则即使跨域的http/https 请求,默认情况下是被禁止的,ip(域名)不同.或者端口不同.协议不同(比如http.htt ...

  8. 08: CORS实现跨域请求

    目录: 1.1 cors跨域请求介绍 1.2 使用tornado实现 复杂请求 1.3 Django中使用django-cors-headers解决跨域问题 1.1 cors跨域请求介绍返回顶部 1. ...

  9. 利用CORS实现跨域请求(转载)

    跨域请求一直是网页编程中的一个难题,在过去,绝大多数人都倾向于使用JSONP来解决这一问题.不过现在,我们可以考虑一下W3C中一项新的特性--CORS(Cross-Origin Resource Sh ...

随机推荐

  1. QQ音乐接口api,包括付费音乐、无损音乐、高品质音乐地址解析接口api

    QQ音乐网站所有音乐(包括付费.无损等版权音乐解析接口地址url). mp3 普通高品 http://dl.stream.qqmusic.qq.com/M5000012gqVh4fFvVK.mp3?v ...

  2. python基础知识第四篇(元组)

    元组 list列表 li[11,22,33,44]列表和元组的区别:元素不可被修改,不可被增加或者删除(一级元素),列表则相反 tuple元组 tu=(111,222,333,444) 支持索引取值 ...

  3. C# yield关键字

    关于yield关键字,网上有很多文章介绍了,但是看了之后,虽然明白了"哦,原来是这么回事",但是在日常开发中并没有真正的用起来,所以,写此一篇,介绍一下在真正的项目中怎么使用这个关 ...

  4. Supermap/Cesium 开发心得----本地视频接入播放

    在三维中,为了增加现实感.给人一种带入感,我们会采取接入视频的方式来实现,那么如何接入视频呢? 由于没有截至写文章为止,我没有视频流数据,所以只能采取本地视频文件的方式来做. 本文介绍结束视频的其中一 ...

  5. 搭建Android开发环境 以及 ionic 编译安卓app步骤

    1. 下载安装JDK 下载地址: https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htm ...

  6. bayaim——听课笔记_01.Docker基础应用 10课.txt

    ===========2019年8月5日18:39:06====================10.20.100.21rootbayaim ==========01-Docker介绍======== ...

  7. linux 定时备份数据库

    说明 检查Crontab是否安装 若没有 需要先安装Crontab定时工具 安装定时工具参考(https://www.cnblogs.com/shaohuixia/p/5577738.html) 需要 ...

  8. 现代“十二要素应用”与 Kubernetes

    "十二要素应用"为开发SaaS应用提供了方法上的指导,而Docker能够提供打包依赖,解耦后端服务等特性,使得两者非常吻合.这篇文章介绍了Docker特性怎样满足了开发" ...

  9. 查看python版本多少位的

    正常我们在cmd终端输入python之后,如果有安装python,就会在回车之后出来关于你安装的python版本信息,几版本,多少位的,但是还有一种,像我这样只显示了python版本是3.7.5,并没 ...

  10. 收藏收藏:工作用了很久的自主开发的Sql Server代码生成器,我开源了(.NET Winform)

    大家好,已经一年没见了,我的技术已经有了惊人的进步.于是乎就来为大家分享技术了,今天呢为大家带来的是很早之前开发的老工具分享给大家. 相信大家都使用过代码生成器,用起来顺手的有多少?根据自己的业务配置 ...