您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

配置跨域后,框架帮我们做了什么?

时间:2020-08-13 16:49:32  来源:  作者:
配置跨域后,框架帮我们做了什么?

 

跨域问题

现在绝大多数公司的项目都是前后端分离的,前后端分离后势必会遇到跨域问题。如下图

配置跨域后,框架帮我们做了什么?

 


继续debug发现,reponse为undefined,提示消息为Network Error。

配置跨域后,框架帮我们做了什么?

 


所以当你和前端联调的时候一直请求失败,报网络错误,一般情况下是后端没有做跨域配置。

注意此时并不是后端没有收到请求,而是收到请求了,也返回结果了,但是浏览器将结果拦截了,并且报错。

 

同源策略

那么浏览器为什么会报错呢?

因为浏览器基于安全考虑而引入的同源策略

配置跨域后,框架帮我们做了什么?

 


协议+域名+端口三者都相同时,才不会产生跨域问题,即同源。此时才能读取到服务端的响应

当前url请求url 是否跨域

https://www.JAVAshitang.comhttp://www.javashitang.com. 是,协议不同https://www.javashitang.comhttp://book.javashitang.com. 是,域名不同https://www.javashitang.comhttp://www.javashitang.com:8000. 是,端口不同

为什么要有同源策略呢?

当然是为了安全起见,举个例子,以银行转账为例,看看你的钱是怎么没的

配置跨域后,框架帮我们做了什么?

 

这就是著名的CSRF攻击(跨站请求伪造,当然还有很多其他方式),还有如果第5步不对请求的来源进行校验,那么你的钱已经被转走了

html页面中的如下三个标签是允许跨域加载资源的

  1. <img src=XXX>
  2. <link href=XXX>
  3. <script src=XXX>

如何解决跨域

虽然同源策略保证了安全,但一些合理的用途也会受到影响。解决跨域的方式有很多种,简单介绍2个

JSONP

JSONP主要是利用<script>标签将请求发送出去,来实现数据的加载,但这种方式有一个缺点,即只能支持GET请求,其他请求都不能支持,因为JSONP这种方式已经很少使用了,所以不做过多的介绍

CROS

非简单请求

在正式的跨域请求前,发送一个OPTIONS请求去询问服务器是否接受接下来的跨域请求,携带如下header

Origin:发起请求原来的域Access-Control-Request-Method:将要发起的跨域请求方式(GET/POST/…)Access-Control-Request-Headers:将要发起的跨域请求中包含的请求头字段

服务器在返回中增加如下header来表明是否允许这个跨域请求。浏览器收到后进行检查如果不符合要求则不会发起后续请求

Access-Control-Allow-Origin:允许哪些域来访问(*表示允许所有域的请求)Access-Control-Allow-Methods:允许哪些请求方式Access-Control-Allow-Headers:允许哪些请求头字段Access-Control-Allow-Credentials:是否允许携带Cookie

简单请求

每次都要发送二次请求是不是很麻烦?所以做了优化

当请求方法是HEAD、GET、POST并且请求头只有如下几个时,被定义为简单请求AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type:(Application/x-www-form-urlencoded、multipart/form-data、text/plain)

简单请求会在请求中加入Origin头,直接发起请求,不会先询问了。后端返回相应的header即可

Spring支持跨域

理解了跨域的本质,再看各种配置其实就是根据请求往reponse中增加header

利用Filter

配置如下Filter,CrossDomainFilter是对javax.servlet.Filter的封装,本质上是一个Filter。

可以看到我多返回了一个header,Access-Control-Max-Age,他表明了询问结果的有效期限,即在3600s之内浏览器可以不必再次询问

@Component
@WebFilter(filterName = "crossDomain", urlPatterns = "/*")
public class CrossDomainFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 此处可以进行白名单检测
        if(CorsUtils.isCorsRequest(request)) {
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
            response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
            response.setHeader("Access-Control-Max-Age", "3600");
        }
        // 是个OPTIONS请求,header已设好,不用执行后续逻辑,直接return
        if(CorsUtils.isPreFlightRequest(request)) {
            return;
        }
        filterChain.doFilter(request, response);
    }
}

看一下用到的工具类

public abstract class CorsUtils {

    // 请求中有 origin 这个header则返会true
    public static boolean isCorsRequest(HttpServletRequest request) {
        return (request.getHeader(HttpHeaders.ORIGIN) != null);
    }

    public static boolean isPreFlightRequest(HttpServletRequest request) {
        return (isCorsRequest(request) && HttpMethod.OPTIONS.matches(request.getMethod()) &&
                request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
    }

}

利用CorsRegistry

@Configuration
public class GlobalCorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                // 添加映射路径
                registry.addMapping("/**")
                        // 允许的域
                        .allowedOrigins("*")
                        // 允许携带cookie
                        .allowCredentials(true)
                        // 允许的请求方式
                        .allowedMethods("GET","POST", "PUT", "DELETE")
                        // 允许的请求头
                        .allowedHeaders("*");
            }
        };
    }
}

利用@CrossOrigin注解

支持更细粒度的配置,可以用法方法上或者类上

@RestController
@RequestMapping("resource")
@CrossOrigin({"http://127.0.0.1:8080"})
public class ResourceController

其他方式支持跨域

看到这你可能会产生疑问,我们的项目中没有跨域的配置啊,怎么还能支持跨域?那估计是把设置header这些活交给网关层来做了。



Tags:框架   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Tags: 框架  点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  Tags: 框架  点击:(11)  评论:(0)  加入收藏
大家好,我是很帅的狐狸今天我打算系统地聊聊资产配置 今儿我打算介绍一个超级无敌实用的资产配置框架。过去几年,我被问到最多的,可能是下面这一类问题&mdash;&mdash; 我有10...【详细内容】
2021-12-14  Tags: 框架  点击:(8)  评论:(0)  加入收藏
1 前言ObjectiveSQL 是一个Java ORM 框架,它不仅是Active Record 模式在Java 中的应用,同时还针对复杂SQL 编程提供近乎完美的解决方案,使得Java 代码与SQL 语句有机的结合,改变...【详细内容】
2021-12-13  Tags: 框架  点击:(13)  评论:(0)  加入收藏
对项目的基本介绍 1.整个框架主要是给MVVM框架使用的,自己写完interface接口后,通过自定义的注解就能自动生成接口方法 2.用Kotlin的Flow去代替Rxjava,因为我发现RxJava功能很...【详细内容】
2021-12-08  Tags: 框架  点击:(16)  评论:(0)  加入收藏
CSS框架提供了设计一致解决方案的基本结构,以解决前端web开发中的常见问题。它们提供了通用功能,可以针对特定场景和应用程序进行覆盖。这大大减少了开始创建应用程序和网站所...【详细内容】
2021-12-06  Tags: 框架  点击:(15)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  Tags: 框架  点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  Tags: 框架  点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30  Tags: 框架  点击:(26)  评论:(0)  加入收藏
项目介绍您可以方便快速地开发微信全平台的应用(包括微信公众号、小程序、小游戏、企业号、开放平台、微信支付、JS-SDK、微信硬件/蓝牙,等等)。本项目的 Demo 同样适合初学者...【详细内容】
2021-11-17  Tags: 框架  点击:(38)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条