目录

跨域请求概述与限制

方式1:Jsonp 解决跨域

方式2:HttpServletResponse 设置响应头跨域

方式3:自定义 servlet 过滤器 filter 实现全局跨域

方式4:CorsFilter 跨域请求全局过滤器

方式5:重写 WebMvcConfigurer(全局跨域)

方式6:@CrossOrigin 注解 (局部跨域)

方式7:Nginx 解决请求跨域


跨域请求概述与限制

1、前后端数据交互经常会碰到请求跨域,浏览器为了安全使用了“同源策略”

2、同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS、CSFR 等攻击。所谓同源是指"协议+域名+端口"三者全部相同,即便两个不同的域名指向同一个 ip 地址,也非同源。

3、不符合同源策略的请求即为“跨域”。

4、同源策略限制内容有:

1)无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

2)无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

3)无法向非同源地址发送 AJAX 请求

5、如下三个标签允许跨域加载资源,这也就是平时为什么可以使用 CDN 地址加载网络上的 JQuery、Bootstrap 的原因:

<img src=XXX>
<link href=XXX>
<script src=XXX>

6、跨域并不是请求发不出去,而是请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

7、跨域的本质是浏览器为了安全而阻止用户读取另一个域名下的内容,所以表单可以进行跨域请求,因为表单不会获取新的内容,而 Ajax 则会被浏览器拦截结果,因为 Ajax 会获取响应,浏览器认为这不安全,所以拦截了响应。

8、这也说明了跨域并不能完全阻止 CSRF(Cross-site request forgery)跨站请求伪造,因为请求毕竟是发出去了,而且服务端也接收到了请求。

常见跨域场景

1、当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域,不同域之间相互请求资源,就算作“跨域”。

URL 描述 是否跨域

http://www.tiger.com/a.js

http://www.tiger.com/b.js

协议、域名、端口相同

http://www.tiger.com/app1/a.js

http://www.tiger.com/app2/b.js

协议、域名、端口相同,应用不同

http://www.tiger.com:8080/a.js

http://www.tiger.com/b.js

协议、域名相同,端口不同

https://www.tiger.com/a.js

http://www.tiger.com/b.js

协议不同、域名、端口相同

http://www.tiger.com/a.js

http://115.25.183.45/b.js

协议、端口相同,域名不同

http://www.tiger.com/a.js

http://cloudServer.tiger.com/b.js

协议、端口相同,主域名相同,子域名不同

2、浏览器只会通过“URL 首部”来识别而不会根据域名对应的 IP 地址是否相同来判断,“URL 首部”可以理解为“协议, 域名和端口必须匹配”。

方式1:Jsonp 解决跨域

1、JSONP(JSON with Padding-填充 JSON)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题

2、JSONP 原理:利用 script 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据,JSONP 请求一定需要对方的服务器做支持才可以。

3、JSONP 和 AJAX 相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式,但 AJAX 属于同源策略,JSONP 属于非同源策略(跨域请求)

4、JSONP 优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题,缺点是 JSONP 仅支持 get 请求,不支持其它的 POST 等请求,不安全可能会遭受 XSS 攻击。

5、关于纯 JSONP 的实现流程可以参考:https://mp.weixin.qq.com/s/LV7qziMyrMt0_EJWo05qkA

6、本文直接介绍最简单快捷的方式,使用 JQuery 的 $.ajax 类发送 get 请求,指定 jsonp 格式返回。

Jsonp - 前端 JavaScript 在线演示源码:https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/InfoController.java

1、 $.ajax({jsonp:"callback"}) 的值会自动拼接在 $.ajax({url:"xxx"})地址中,自己可以指定任意的值,当不写 jsonp 属性时,JQuery 默认也是使用 "callback" 作为值。

2、$.ajax({jsonp:"callback"}) 的值服务器端是要获取然后封装值返回的,如 callback({"name":"zhangSan"});后台返回的 json 数据必须放在 callback(xxx) 中。所以跨域请求时,前后端一定要商量好,仅仅只是前端使用了 jsonp ,服务器没有特殊处理时,也是不行的。

Jsonp - 后端 - java 在线演示源码:https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/InfoController.java

方式2:HttpServletResponse 设置响应头跨域

1、CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源(协议 + 域名 + 端口)服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

2、CORS 需要浏览器和后端同时支持,浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域,与前端代码无关。

3、服务器响应客户端的时候,带上 Access-Control-Allow-Origin 头信息则可以开启 CORS, 该属性表示哪些域名可以访问资源,通配符 “*” 表示所有网站都可以访问此资源。

response.setHeader("Access-Control-Allow-Origin", "*");    #允许所有域名的脚本访问该资源
response.setHeader("Access-Control-Allow-Origin", "http://192.168.1.20:55555");  #允许指定的域名的脚本访问该资源

指定某个具体的域名可以访问时,根据同源策略只需要写 协议:/域名:端口 即可,不需要指定应用。

4、如上所示浏览器 F12 开发者工具中随便点击一个请求,就可以看到很多服务器设置的就是允许所有来源的脚本进行访问。

5、Access-control-Allow-Origin 多域名设置:头信息中的 Access-Control-Allow-Origin 只允许一个值,所以不能用逗号分隔多个值,如下所示是错误的:

Access-Control-Allow-Origin: https://www.google.com,https://www.baidu.com 

推荐思路是自己使用 List、Set、Array 等容器存放所有可以访问的域名当做白名单,以后当有请求时动态判断此域名是否在白名单之内,是则放行,否则不处理,客户端也就无法访问成功。

这里有个点:如何获取请求的源呢?即用户是从哪个 "协议://域名:端口 "的应用发起访问的呢?可以在浏览器中 F12 打开开发者工具看到请求的头信息中自动带了 Origin 信息,服务器只需要获取即可。

在线演示源码:
https://gitee.com/wangmx1993/java-se/blob/master/src/main/resources/static/cors/cors_response.html
https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/InfoController.java

6、通常只需要使用 Access-Control-Allow-Origin 就够用了,但是还可以设置以下其它的头信息:

    // 设置哪个源可以访问我
    res.setHeader('Access-Control-Allow-Origin', origin)
    // 允许携带哪个头访问我
    res.setHeader('Access-Control-Allow-Headers', 'name')
    // 允许哪个方法访问我
    res.setHeader('Access-Control-Allow-Methods', 'PUT')
    // 允许携带cookie
    res.setHeader('Access-Control-Allow-Credentials', true)
    // 预检的存活时间
    res.setHeader('Access-Control-Max-Age', 6)
    // 允许返回的头
    res.setHeader('Access-Control-Expose-Headers', 'name')

方式3:自定义 servlet 过滤器 filter 实现全局跨域

1、上面方式2的 HttpServletResponse 设置响应头信息,只能为每个方法单独设置,如果需要为整个应用进行设置,可以在过滤器中进行统一过滤设置。

2、Spring Boot @ServletComponentScan 扫描 @WebFilter 自定义过滤器,启动类上必须添 @ServletComponentScan 注解对 servlet 注解进行扫描,如 @WebServlet、@WebFilter、@WebListener,这样才会生效。

3、在线演示源码:
https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/MyCorsFilter.java
https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/JavaseApplication.java

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 自定义 servlet 过滤器全局设置跨域请求,与 {@link InfoController#postInfo} 完全同理,只是提升为全局设置* * 标准 Servlet 过滤器,实现 javax.servlet.Filter 接口,并重现它的 3 个方法* * filterName:表示过滤器名称,可以不写* * value:配置请求过滤的规则,如 "/*" 表示过滤所有请求,包括静态资源,如 "/user/*" 表示 /user 开头的所有请求** @author wangMaoXiong* @version 1.0* @date 2021/6/6 10:02*/
@WebFilter(filterName = "MyCorsFilter", value = {"/*"})
public class MyCorsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("com.wmx.servlet.SystemFilter -- 系统启动...");}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {//转为 HttpServletRequest 输出请求路径HttpServletRequest request = (HttpServletRequest) req;System.out.println("com.wmx.servlet.SystemFilter -- 过滤器放行前...." + request.getRequestURL());HttpServletResponse response = (HttpServletResponse) res;response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");filterChain.doFilter(req, res);System.out.println("com.wmx.servlet.SystemFilter -- 过滤器返回后...." + request.getRequestURL());}@Overridepublic void destroy() {System.out.println("com.wmx.servlet.SystemFilter -- 系统关闭...");}
}

方式4:CorsFilter 跨域请求全局过滤器

1、提供一个自定义的 @Configuration 配置类,然后自定义 CorsFilter 过滤器,添加映射路径和具体的 CORS 配置路径。

2、前端在线演示源码(一个普通的  get 请求):https://gitee.com/wangmx1993/java-se/blob/master/src/main/resources/static/cors/cors_filter.html

3、后端 CorsFilter 配置在线演示源码:https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/GlobalCorsConfig.java

4、注意 127.0.0.1 和 localhost 也会被当做不同的主机,多个时可以使用 addAllowedOrigin 多次添加添加。

方式5:重写 WebMvcConfigurer(全局跨域)

1、实现 WebMvcConfigurer(全局跨域) 重写 addCorsMappings 方法设置跨域映射。

2、在线演示源码:https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/MyWebMvcConfigurer.java

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 实现 WebMvcConfigurer(全局跨域) 重写 addCorsMappings 方法设置跨域映射** @author wangMaoXiong* @version 1.0* @date 2021/6/6 8:08*/
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {//CorsRegistration addMapping(String pathPattern): 添加路径映射,如 /admin/info,或者 /admin/**registry.addMapping("/**")//是否发送Cookie.allowCredentials(true)//放行哪些原始域, * 表示所有.allowedOrigins(new String[]{"http://127.0.0.1:63342","http://localhost:63342"})//放行哪些请求方式.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})//放行哪些原始请求头部信息.allowedHeaders("*");//暴露哪些头部信息,不能设置为 * : .exposedHeaders();}
}

方式6:@CrossOrigin 注解 (局部跨域)

1、@CrossOrigin 如果定义在类上,则对类中的所有方法生效,定义在方法上则对方法生效。

2、多种跨域方式配置同时存在时,优先级是采用就近原则。

3、在线演示源码:
https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/cors/CrossOriginController.java
https://gitee.com/wangmx1993/java-se/blob/master/src/main/resources/static/cors/cross_origin.html

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/*** @author wangMaoXiong* @version 1.0* @date 2021/6/6 8:37*/
@RestController
public class CrossOriginController {/*** @CrossOrigin 如果定义在类上,则对类中的所有方法生效,定义在方法上则对方法生效,优先级是采用就近原则,属性如下:* String[] origins() default {}:允许哪些请求源可以访问,默认为 * 所有源都可以访问* String[] value() default {}:等同于 origins* String[] allowedHeaders() default {}:允许的请求头列表,默认为 * ,允许所有* String[] exposedHeaders() default {}:对外暴露的头信息,如 Cache-Control,Content-Language,等等,默认不会暴露任何信息* RequestMethod[] methods() default {}:允许的请求方式,默认为 get、post、head*/@GetMapping("/crossOrigin/getInfo")@CrossOrigin(origins = "*")public Map<String, Object> getInfo() {Map<String, Object> dataMap = new HashMap<>(4);dataMap.put("code", 200);dataMap.put("msg", "success");dataMap.put("data", null);dataMap.put("times", System.currentTimeMillis());return dataMap;}
}

方式7:Nginx 解决请求跨域

Nginx 解决请求跨域:https://wangmaoxiong.blog.csdn.net/article/details/89305238

Spring boot 跨域请求实现方式汇总相关推荐

  1. spring boot 跨域请求_SpringBoot 系列教程 web 篇之自定义请求匹配条件 RequestCondition...

    191222-SpringBoot 系列教程 web 篇之自定义请求匹配条件 RequestCondition 在 spring mvc 中,我们知道用户发起的请求可以通过 url 匹配到我们通过@R ...

  2. webmvcconfigurer配置跨域_为什么加了 Spring Security 会导致 Spring Boot 跨域失效呢?...

    点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达 作者:欧阳我去 链接:https://segmentfault.com/a/1190000019485883 作为一个后端开发,我们经常遇到 ...

  3. 实战系列-Spring Boot跨域解决方案

    导语   在实际工作开发中经常会遇到跨域请求,这个时候就需要前后端来共同协调来解决问题,那么在Spring Boot中怎么解决跨域请求问题呢?下面就来看看 什么是跨域   为了保证浏览器的安全,不同源 ...

  4. Spring处理跨域请求

    [nio-8080-exec-8] o.s.web.cors.DefaultCorsProcessor        : Skip CORS processing: request is from s ...

  5. java后端实现CROS跨域请求的方式

    跨域: 跨域就是请求的url中的"协议"."域名"."端口号"其中任何一种不一样都是属于跨域.解决跨域的主要的四种方法是jsonp.跨域资源 ...

  6. 本地Vue前端请求本地Spring Boot跨域问题(CROS错误)

    一.Vue前端 请求的url为 : GET /WebServer/home/get-user-info?id=1 二.Spring Boot后端 是一个Get请求的RestFul接口地址,且后端应用的 ...

  7. spring boot跨域问题

    跨域是指不同域名之间相互访问.跨域,指的是浏览器不能执行其他网站的脚本.它是浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制.也就是如果在A网站中,我们希望使用Ajax来获得B网站 ...

  8. PHP后端API接口解决Ajax跨域请求的方式

    如果我们是前后端分离,且不再同一域的情况下,前端使用Ajax请求后端的数据的时候,就会出现跨域的问题. 在前端我们可以使用获取jsonp格式来应对跨域问题,但是这种方式比较难用,如果前端后端都是可以进 ...

  9. Spring Boot跨域解决方案

    一.什么是跨域 为保证浏览器的安全,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,这称之为同源策略,如果一个请求地址里的协议.域名.端口号都相同,就属于同源.依据浏览器同源策略,非同源脚 ...

  10. Spring配置跨域请求

    本文主要是Spring+SpringMVC+MyBatis/MyBatis Plus框架环境,包括SpringBoot同样适用. 1.编写拦截器 package com.interceptor;imp ...

最新文章

  1. linux下卸载mysql(rpm)
  2. html列表拖拽排序插件,JS拖拽排序插件Sortable.js用法实例分析
  3. Maven - 快速创建Java工程和Web工程
  4. 期货市场技术分析02_趋势的基本概念
  5. OUTLOOK邮箱设置
  6. 19.TCP/IP 详解卷1 --- TCP 的交互数据流
  7. 图片怎样把背景去掉?怎么把图片背景透明?
  8. 8款主流Scrum敏捷开发工具评测,建议先马后看!
  9. 你能说更多关于崩坏3琪亚娜的细节吗
  10. ubuntu下安装三维渲染引擎OSG详解
  11. 某招聘网站“数据分析”相关岗位招聘信息爬取并分析
  12. 【个人作品】推荐一个SIP客户端-软电话,基于SIP协议,语言C++,界面QT4 开源,asterisk,tribox测试成功
  13. QtCreator 下使用glut.lib glut.dll
  14. solidworks打开大型装配体特别卡。跑不满内存、CPU、GPU。
  15. 论文查重是免费的吗?
  16. 合力提升技术管网治网能力,共同为长三角的数字化发展贡献网信力量
  17. Insight.Numerics.inFlux.v1.0通风和气体扩散CFD软件
  18. java类的心得_java面向对象学习心得3篇
  19. 【时间序列】从移动平均到指数平滑
  20. JavaWeb和WebGIS学习笔记(三)——GeoServer 发布shp数据地图

热门文章

  1. select完成单线程,多用户
  2. Windows下PHP安装配置
  3. java注释 加粗_Java绘图技术,swing画图工具,文字,图片素材,注释,个人理解,星空等【诗书画唱】...
  4. 拓端tecdat|Python支持向量回归SVR拟合、预测回归数据和可视化准确性检查实例
  5. c++下字符串分割函数split实现
  6. log4j打印不出日志_日志框架详细解读
  7. wordpress审查元素修改php,WordPress 教程:如何通过 PHP 代码修改表结构和索引
  8. ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
  9. labelme 将自己数据集实现自动标注
  10. matplotlib中文乱码的两种解决方案