给妹子讲完跨域非要让我去她家!

Posted 结构化思维wz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了给妹子讲完跨域非要让我去她家!相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

本文参考自江南一点雨的Spring Boot+Vue系列视频教程第 3 章,详情参加【Spring Boot+Vue系列视频教程
跨域问题是开发中常见的问题!下面先介绍什么是跨域问题,也是我看一篇好文章学到的。

看看你是怎么给妹子解释跨域的??

小美:geigei,geigei为什么会有跨域问题?		
你: 因为浏览器的同源策略导致了跨域.			
-------------------------------------------------------------------------
小美:浏览器为什么要搞这么麻烦的同源策略? 5555~
你: 同源策略限制了从同一个源加载的文档或脚本 如何与 来自另一个源的资源进行交互。
     这是一个用于隔离潜在恶意文件的重要安全机制。
--------------------------------------------------------------------------
小美:没看懂,好像说是为了安全,就像哥哥.....
你:咳咳!浏览器是从两个方面去做这个同源策略的,一是针对接口的请求,二是针对Dom的查询。
---------------------------------------------------------------------------
小美:那如果不..抱歉哥哥。我说的是如果没有同源策略会怎样呢?
你:首先没有同源策略的接口请求:cookie你应该知道吧?
	   假如你登录某购物网站,如果你请求了接口进行登录,服务端验证通过后会在响应头加入Set-Cookie字段
	   然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中。
	   然后你在购物网站推荐里不小心搜了一个“透“字,你便熟练地打开了另一个小网站
	   但是这个小网站很坏,背地里居然向你刚才的购物网站发送请求。
	   由于没有同源策略,这个小网站就登录了你的账号,为所欲为了一翻! 这就是传说中的CSRF攻击
	   没有同源策略限制的Dom查询:有天早上你还没睡醒,突然接到短信说你中了500w
	   你赶紧点开连接,输入了银行密码查询,事后才发现原来是钓鱼网站。
	   如果没有同源策略,钓鱼网站就可以拿到别的网站的Dom
	   天上哪有馅饼,都是为了你兜里的两块五毛钱啊!!!!
------------------------------------------------------------------------------	
小美:好可怕好可怕,浏览器这个同源策略还是很好的呢,这么看来
你 : 邪魅一笑,但是!只要我是正人君子是可以实现跨域的!打开方式正确:
     同源策略限制下接口请求的正确打开方式:1.JSONP 2.空iframe加form 3.CORS 4.代理 	
	 同源策略限制下Dom查询的正确打开方式:1.postMessage 2.document.domain 3.canvas操作图片的跨域问题
--------------------------------------------------------------------------------	
小美:哥哥你能具体说说吗??对了去我家教教我,我家没人...
你 : 虽然哥哥是正人君子,但是我很乐意传授知识

本文只传授一波CORS吧!这也是现在主流的跨域方式

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
看名字就知道这是处理跨域问题的标准做法。
CORS有两种请求,简单请求和非简单请求。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST

(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

总结:

所谓同源是指协议、域名以及端口要相同。同源策略是基于安全方面的考虑提出来的,这个策略本身没问题,但是我们在实际开发中,由于各种原因又经常有跨域的需求,传统的跨域方案是JSONP,JSONP虽然能解决跨域但是有一个很大的局限性,那就是只支持GET请求,不支持其他类型的请求,而今天我们说的CORS(跨域源资源共享)(CORS,Cross-origin resource sharing)是一个W3C标准,它是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,这是JSONP模式的现代版。

域:协议+域名/IP+端口 有一个不一样就是跨域了,同源策略就只能请求相同域中的资源。

域检请求,当请求不是简单请求的时候,在发送之前会先检查服务端是否支持要发送的请求,服务端会告诉客户端支持什么请求。

====================================================================
在Spring框架中,对于CORS也提供了相应的解决方案,今天我们就来看看SpringBoot中如何实现CORS。

SpringBoot中如何实现CORS。

案例:

需求:两个不同的项目同时运行(端口号不一样),跨域了,如何让第二个项目直接访问到第一个项目中的资源?

环境搭建:

  • 有两个工程cors01和cors02,一个提供服务一个消费服务
  • cors01 端口号:8080 cors02端口号:8088
  • 在cors01 提供两个hello接口,一个get,一个post
  • 在cors02 中创建一个html,发送一个简单的Ajax请求

同时运行,点击请求按钮观察。

编码:cors01(提供服务)

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
    @PostMapping("/hello")
    public String hello2() {
        return "post hello";
    }

}

编码:cors02(消费服务)

  • 修改端口

    server.port=8088
    
  • 发送简单的Ajax请求

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>消费服务</title>
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    </head>
    <body>
    <div id="app"></div>
    <input type="button" onclick="btnClick()" value="get_button">
    <input type="button" onclick="btnClick2()" value="post_button">
    <script>
      function btnClick() {
        $.get('http://localhost:8080/hello', function (msg) {
          $("#app").html(msg);
        });
      }
    
      function btnClick2() {
        $.post('http://localhost:8080/hello', function (msg) {
          $("#app").html(msg);
        });
      }
    </script>
    </body>
    </html>
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>消费服务</title>
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    </head>
    <body>
    <div id="app"></div>
    <input type="button" onclick="btnClick()" value="get_button">
    <input type="button" onclick="btnClick2()" value="post_button">
    <script>
      function btnClick() {
        $.get('http://localhost:8080/hello', function (msg) {
          $("#app").html(msg);
        });
      }
    
      function btnClick2() {
        $.post('http://localhost:8080/hello', function (msg) {
          $("#app").html(msg);
        });
      }
    </script>
    </body>
    </html>
    
    

未处理跨域时:

在这里插入图片描述

如何实现跨域呢??

1.@CrossOrigin注解配置某一个方法接受某一个域的请求

@CrossOrigin中的值表示允许来自对应值的接口访问

@RestController
public class HelloController {
    @CrossOrigin(value = "http://localhost:8088")
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
    @PostMapping("/hello")
    @CrossOrigin(value = "http://localhost:8088")
    public String hello2() {
        return "post hello";
    }

}

测试:
在这里插入图片描述

@CrossOrigin( )中还有好多跨域先关的设置,小伙伴们可以自行查看源码。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
    /** @deprecated */
    @Deprecated
    String[] DEFAULT_ORIGINS = new String[]{"*"};
    /** @deprecated */
    @Deprecated
    String[] DEFAULT_ALLOWED_HEADERS = new String[]{"*"};
    /** @deprecated */
    @Deprecated
    boolean DEFAULT_ALLOW_CREDENTIALS = false;
    /** @deprecated */
    @Deprecated
    long DEFAULT_MAX_AGE = 1800L;

    @AliasFor("origins")
    String[] value() default {};

    @AliasFor("value")
    String[] origins() default {};

    String[] originPatterns() default {};

    String[] allowedHeaders() default {};

    String[] exposedHeaders() default {};

    RequestMethod[] methods() default {};

    String allowCredentials() default "";

    long maxAge() default -1L;
}

2.全局配置的方法

创建一个类实现WebMvcConfigurer接口,重写addCorsMappings方法

/**
 * @author: 王泽
 *
 * /**表示本应用的所有方法都会去处理跨域请求
 * allowedMethods表示允许通过的请求数
 * allowedHeaders则表示允许的请求头。
 * 经过这样的配置之后,就不必在每个方法上单独配置跨域了。
 */

public class WebCros implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8088")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

------------------------------------------------注意----------------------------------------------------------------
了解了整个CORS的工作过程之后,我们通过Ajax发送跨域请求,虽然用户体验提高了,但是也有潜在的威胁存在,常见的就是CSRF(Cross-site request forgery)跨站请求伪造。跨站请求伪造也被称为one-click attack 或者 session riding,通常缩写为CSRF或者XSRF,是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法,举个例子:

假如一家银行用以运行转账操作的URL地址如下:http://icbc.com/aa?bb=cc,那么,一个恶意攻击者可以在另一个网站上放置如下代码:<img src="http://icbc.com/aa?bb=cc">,如果用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会遭受损失。

基于此,浏览器在实际操作中,会对请求进行分类,分为简单请求,预先请求,带凭证的请求等,预先请求会首先发送一个options探测请求,和浏览器进行协商是否接受请求。默认情况下跨域请求是不需要凭证的,但是服务端可以配置要求客户端提供凭证,这样就可以有效避免csrf攻击。

------------------------------------------------注意----------------------------------------------------------------

相信看到这里,小伙伴们也都明白springboot中如何实现跨域了吧,还望大家三连支持!

在这里插入图片描述

以上是关于给妹子讲完跨域非要让我去她家!的主要内容,如果未能解决你的问题,请参考以下文章

搞了快10年的测试,如今被一应届生取代了...这是要让我去跑滴滴!

我向往的生活,李子柒奶奶的生活

妹子:为什么我要找个程序员做老公?

Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段

跨域带cookie失效的解决方案

盛事通上传oss失败