zoukankan      html  css  js  c++  java
  • spring boot 中通过CORS实现跨域

    一、跨域问题出现的原因 

      出现跨域问题的原因是同源策略。

      同源策略

      主要是三同:同协议、同域名、同端口,

      同源策略目的

    • 保证用户信息安全,防止恶意网站窃取数据。同源策略是必须的,否则cookie可以共享。

      同源策略的限制范围

    • cookie、localstorage、indexdb无法读取。
    • DOM无法获取。
    • ajax请求不能发送。

      规避策略

    1. cookie:设置document.domain共享cookie。
    2. DOM获取:(父子页面通信)H5引入了一个API,这个API为windows对象新增了一个window.postMessage方法,允许跨窗口通信,无论这两个窗口是否同源。
    3. window.opener.postMessage(content,origin)
      
      content是消息的具体内容,origin是协议 + 域名 + 端口
    1. AJAX:
    • JSONP:JSONP是服务器无客户端跨源通信的常用方法。基本思想是网页通过添加一个<script>元素,向服务器请求json数据,这种做法不受同源政策的限制,服务器收到请求后,将数据放在一个指定名字的回调函数里面传回来。(只能发GET请求)
    • WebSocket:WebSocket是一种通信协议。使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
    • CORS:详解如下。

      跨域资源共享(corss-origin resource sharing):CORS需要浏览器和服务器同时支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

      两种请求

    • 浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

      CORS请求

      1. 简单请求

    • 对于简单请求,浏览器直接发出CORS请求。具体来说,就是在Header中增加一个Origin字段。如果浏览器发现跨源AJAX请求是简单请求,就自动在头信息之中,添加一个Origin字段。
    GET /cors HTTP/1.1      
    Origin: http://localhost:8081     //浏览器添加字段,说明本次请求来自哪个源(协议+域名+端口)。
    Host: 119.23.214.114
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0...
    • 如果Origin指定的源在不在后端的许可白名单范围内,服务器会返回一个正常的http回应。浏览器接收后发现,这个response的Header没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。这种错误无法通过状态码识别,因此HTTP response的状态码有可能是200。

      2. 非简单请求

    • 非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json
    • 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
      以上内容链接:https://www.jianshu.com/p/413a2f11828d

    二、spring boot 通过CORS解决跨域问题

      先创建一个项目server作为服务器端,默认端口为8080,并在服务端提供两个接口:

    //方便client分别发送不同类型请求的时候可以 观察一下简单请求和非简单请求的区别
    @RestController
    public class HelloController { @GetMapping("gethello") //get 类型public String getHello(){ return "get hello"; } @PutMapping("puthello") //put类型 public String putHello(){ return "put hello"; } }

      再创建一个项目client作为请求端,并设置请求端的端口为8081:

    server.port=8081

    在请求端的resources/static目录下增加本次访问所需要的页面index.html,记得同时自己找一个jquery.min.js 也放到static目录下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="jquery.min.js"></script>
    </head>
    <body>
    <div id="div"></div>
    <input type="button" value="获取" onclick="gethello()"> //用于测试简单请求
    <input type="button" value="更新" onclick="puthello()"> //用户测试非简单请求
    <script>
        function gethello() {
            $.get('http://localhost:8080/gethello',function (msg) {
                $("#div").html(msg); //将调用接口返回值在页面上显示
            });
        }
        function puthello() {
           $.ajax({
               type:'put',
               url:'http://localhost:8080/puthello',
               success:function (msg) {
                   $("#div").html(msg);
               }
           })
        }
    </script>
    </body>
    </html><!DOCTYPE html>

        接下来看看跨域失败的的时候:首先启动server端,再启动client端。在浏览器中访问:http://localhost:8081/index.html,点击获取按钮:

      然后我们在服务端中通过CORS解决跨域的问题,有两种解决办法。

      1.在接口类或者方法上面添加 @CrossOrigin注解

       @GetMapping("gethello")
        @CrossOrigin(value = "http://localhost:8081") //指定可以访问的白名单
        public String getHello(){
            return "get hello";
        }

      2.实现WebMvcConfigurer接口重写addCorsMappings方法

    
    
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
           registry.addMapping("/**").allowedOrigins("http://localhost:8081")
                    .allowedMethods("*")
                    .allowedHeaders("*")
              
    .maxAge(30000);
    } }

       解决了跨域问题后,重启服务端:再进行获取和更新操作:

      1.获取操作 成功

      

      2.更新操作

      正如前面所说的非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

  • 相关阅读:
    图形2d,3d加速简介
    [转]startx启动过程分析
    initrd.img、vmlinux和 vmlinuz
    TSQL建主键索引语句 / 外键
    ASP.NET MVC 2.0在WinXP IIS6下的部署
    update中加入select
    Request
    jqGrid使用总结
    Jquery 表单取值赋值 处理返回json数据
    108个搞笑经典短句(转)
  • 原文地址:https://www.cnblogs.com/hopeofthevillage/p/11741327.html
Copyright © 2011-2022 走看看