springboot之跨域访问cros,@CrossOrigin注解

Posted 笨不拉几的菜鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot之跨域访问cros,@CrossOrigin注解相关的知识,希望对你有一定的参考价值。

目录

一、url

二、同源的含义

三、浏览器的同源策略

四、跨域访问

 1、什么是跨域访问

 2、为什么前后端分离项目会产生跨域问题

 3、跨域过程分析

五、cros解决跨域访问

六、@CrossOrigin注解

一、url

   url(uniform resource locator:统一资源定位符)

   协议://域名:端口号/资源路径/文件名

二、同源的含义

所谓同源,就是指请求的资源url和目前文件来源url的协议域名端口都相同。同源即同域,两者意思相同。

举例:网址:http://www.oneRound.com/dir/page.html ,它的协议是http://,域名是www.oneRound.com ,端口是80(http协议在没有指定端口号时,默认端口号是80)。

将表格中的url与 http://www.oneRound.com/dir/page.html 比较判断是否同源
url是否同源原因
http://www.oneRound.com/dir/page/index.html资源路径和文件名不同,但三要素相同
http://www.round.com/dir/page.html域名不同
https://www.oneRound.com/dir/page.html协议和端口号都不同(http协议的默认端口号为80,https协议的默认端口号为443)
http://www.oneRound.com:8080/dir/page.html端口号不同(端口号不写时,端口号为该协议默认的端口号)

三、浏览器的同源策略

浏览器的同源策略是指:js脚本在未经允许的情况下,不能够访问其他域下的内容,以保证用户信息的安全,防止恶意的网站窃取数据。

同源策略主要限制:

1、一个域下的js脚本不能访问另一个域下面的cookie,localStorage和indexDB

2、一个域下的js脚本不能够操作另一个域下的DOM

3、ajax不能做跨域请求

1、限制cookie 等信息的跨源网页读取,为了防止恶意网站通过js获取用户其他网站的cookie,是为了保护本地用户信息

2、限制dom的操作,因为恶意网站可以通过iframe打开系统界面,如果可以获取DOM就相当于可以获取整个系统界面的信息。

3、限制跨域 ajax 请求,是为了保护被跨域请求的服务器中数据库用户信息,更加准确地说是跨域请求能发出去,服务器端能收到请求并正常返回结果,但是结果被浏览器拦截了

 特殊:script标签,img标签,以及link标签可以链接其他域中的资源, 因为这些标签不能通过相应的结果来进行安全问题的操作。

四、跨域访问

 1、什么是跨域访问

    从 A 向 B 发请求,如果他们的url非同源,直接访问就会造成跨域问题。跨域是客户端问题,跨域请求有两种情况:

    ①普通的图片、css文件请求,不报错               

    ②发送Ajax请求,报错

        发起跨域请求 --> 浏览器在请求的header上添加origin字段 --> 请求成功发送到服务器 --> 服务器将数据返回给浏览器 --> 服务器返回的响应头中,没有告诉浏览器哪个域名可以访问这些数据(没有设置 Access-Control-Allow-Origin)--> 浏览器将丢弃数据,抛出错误

 2、为什么前后端分离项目会产生跨域问题

     前后端分离的应用,前端、后端是2个独立的应用,运行在不同端口。在浏览器看来,是不同的域,由于浏览器同源策略的限制,导致不同源之间的通信。前端页面中的ajax请求后端接口,即跨域访问。

 3、跨域过程分析

     浏览器对前端页面和后台交互url判断,若同源,则直接发送数据请求;若不同源,则发送跨域请求 ---->
     判断跨域请求。非简单请求:浏览器会帮我们自动触发预检请求,用于确认请求内容是否符合服务端的要求,如果符合,在进行正式的请求。简单请求:直接发出正常请求。---->
     服务器收到浏览器跨域请求后,根据自身配置返回对应文件头。若未配置允许跨域,即文件头里不包含 Access-Control-Allow-origin 字段,若配置过域名,则返回 Access-Control-Allow-origin + 对应配置规则里的域名的方式。 ---->
     浏览器根据接收到的响应头里的 Access-Control-Allow-origin 字段判断,若无该字段,说明不允许跨域,抛出一个错误;若有该字段,对字段内容和当前域名做比对,如果同源,即允许跨域,浏览器接受该响应;若不同源,即该域名不可跨域,浏览器不接受该响应,并抛出一个错误。

cros跨域请求之简单请求、复杂请求

简单请求:

 简单请求的内容:

  请求方法:get、post、head

  HTTP的头信息不超出以下几种:Accept 、Accept-Language、Content-Language、

                                                            Content-Type

  Content-Type的值只有以下三种:text/plain、multipart/form-data、application

  请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件,XMLHttpRequestUpload对象可以使用 XMLHttpRequest.upload 属性访问

  请求中没有使用 ReadableStream 对象

简单请求的部分响应头如下:

1.Access-Control-Allow-Origin(必含)- 不可省略,否则请求按失败处理。该项控制数据的可见范围,如果希望数据对任何人都可见,可以填写"*"。

2.Access-Control-Allow-Credentials(可选) – 该项标志着请求当中是否包含cookies信息。与请求时的withCredentials属性保持一致。

3.Access-Control-Expose-Headers(可选) – 该项确定XmlHttpRequest2对象当中getResponseHeader()方法所能获得的额外信息。通常情况下,getResponseHeader()方法只能获得如下的信息: Cache-Control 、Content-Language、 Content-Type、Expires、 Last-Modified 、Pragma 当你需要访问额外的信息时,就需要在这一项当中填写并以逗号进行分隔。

复杂请求:

 复杂请求的内容:

    先发送一次“预请求”,浏览器会询问服务器,当前所在的网页是否在服务器允许访问的范围内,以及可以使用哪些HTTP请求方式和头信息字段,只有得到肯定的回复,才会进行正式的HTTP请求。预请求以OPTIONS形式发送,当中同样包含Origin,并且还包含了两项CORS特有的内容:

    Access-Control-Request-Method – 该项内容是实际请求的种类,可以是GET、POST之类的简单请求,也可以是PUT、DELETE等等。

    Access-Control-Request-Headers – 该项是一个以逗号分隔的列表,当中是复杂请求所使用的头部。

复杂请求的预请求的响应头如下:

1.Access-Control-Allow-Origin(必含) – 和简单请求一样的,必须包含一个域。

2.Access-Control-Allow-Headers -- 可以返回所有支持的头部。

3.Access-Control-Allow-Credentials(可选) – 和简单请求当中作用相同

4.Access-Control-Allow-Methods(必含) – 这是对预请求当中Access-Control-Request-Method的回复,这一回复将是一个以逗号分隔的列表。尽管客户端或许只请求某一方法,但服务端仍然可以返回所有允许的方法,以便客户端将其缓存。

5.Access-Control-Max-Age(可选) – 以秒为单位的缓存时间。Access-Control-Max-Age这个响应首部表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 能够被缓存的最长时间,单位是秒。


本块内容原文链接:https://blog.csdn.net/qq_36582776/article/details/123670373

五、cros解决跨域访问

    注:跨源请求的本质是请求别人的信息,所以能否跨域请求,是由被请求的服务器的设置决定的。 

    w3c提出跨域资源共享,CORS机制 。CORS 是 Cross-Origin-Resource-Sharing  的缩写,是一种安全机制,当浏览器检测到发送的请求非同源(即跨域)时,会自动在 http 头部添加一个 origin 字段,解决跨域问题的关键就是在服务端的响应头中设置Access-Control-Allow-Origin,即可完成跨域数据获取。

在后台实现跨域的设置,前台就可以访问了

  • 当浏览器发送一个跨域请求时会在 http 头部自动加上 Origin
  • 需要服务端配合设置响应头 Access-Control-Allow-Origin:*|Origin 才可完成跨域

六、springboot web项目使用Cros解决跨域

前端的url:http://localhost:8082

后端的url:http://localhost:8086

1、配置全局跨域访问

 在项目路径下创建config文件夹,在config文件夹下创建CrosConfig类实现WebConfigConfigurer

@Configuration
public class CrosConfig implements WebMvcConfigurer 
    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**") //**匹配的是我们所有后台的路径,代表后台共享了什么资源
                .allowedOrigins("http://localhost:8082") //匹配的前台的服务器地址
                .maxAge(300 * 1000)
                .allowedHeaders("*")
                .allowedMethods("*"); //允许的前台的请求方式

    

使用示例:

成功! 

2、@CrossOrigin注解

作用

在controller上添加@CrossOrigin注解用来开启跨域请求,让其他域的请求可以访问该controller,否则所有其他域的访问会全部被拒绝。

详解

origin属性:允许可访问的域列表

maxAge:准备响应前的缓存持续的最大时间(以秒为单位)

使用位置

①类

 ②方法

①@CrossOrigin注解用在类上

整个类的方法都可以被允许的域访问

后端controller

@Controller
@CrossOrigin("http://localhost:8082")
//@RequestMapping("/emp")
public class EmpController 
    @Autowired
    private IEmpService empService;


    @RequestMapping("/getConformEmp")
    @ResponseBody
    public String getConformEmp(@RequestBody Map<String,String> map) 
        System.out.println(map);
        String name = map.get("name");
        String age = map.get("age");
        return  name + "今年" + age + "岁了!";
    

 前端(以Vue为例)

methods:
    getInfo()
      this.$http.post("/getConformEmp","name":"小明","age":"19").then(res => 
        this.pInfo = res.data
      )
    
  

成功!

 ②注解用在方法上

有注解的方法可以被指定的域访问

 跨域访问“/getConformEmp”:成功!

跨域访问“/getConformEmp01”:失败!

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因

问题

在配置跨域的@Configuration的时候,发现无论是.allowedOrigns()还是.allowedOriginParrtens()都解决不了的时候请看。

问题的根本原因

SpringBoot配置的版本问题

配置方法

SpringBoot 2.2.X版本

@Configuration
public class CrosConfig extends WebMvcConfigurationSupport 

    @Override
    protected void addCorsMappings(CorsRegistry registry) 
        super.addCorsMappings(registry);
        registry.addMapping("/**")
                .allowedMethods("*")
                .allowedOrigins("*")
                .allowedHeaders("*");
    

SpringBoot 2.5.X版本

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;


import java.util.Collections;

@Configuration
public class CrosConfig 
    @Bean
    public CorsFilter corsFilter() 
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1,允许任何来源
        corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
        //2,允许任何请求头
        corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
        //3,允许任何方法
        corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
        //4,允许凭证
        corsConfiguration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    

以上是关于springboot之跨域访问cros,@CrossOrigin注解的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因

前后端分离之跨域问题

samesite是否可以影响cros跨域

记一次vue 使用axios跨域问题(CROS)