• 什么是跨域,为什么会有跨域问题的出现


    【问题】

    使用allure生成报告,当报告用本地的文件夹直接打开html文件之后,发现页面资源都加载不出来...只有用

    npm run open-allure

    才能正常加载出来

    页面某些资源请求失败,打开浏览器F12发现提示:

    from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.

    其实是浏览器 同源策略 问题,或者叫 跨域问题 
    常见于用Chrome调试脚本的时候,需要加载的脚本和location不同源

    【跨域】

    浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域

    为什么会有跨域

    在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问问题。在请求的过程中我们要想回去数据一般都是post/get请求,所以..跨域问题出现

    跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号(如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。

    跨域问题是针对JS和ajax的,html本身没有跨域问题,比如a标签、script标签、甚至form标签(可以直接跨域发送数据并接收数据)等

    跨域的方案

    CORS: 服务器设置允许,浏览器要能够识别这个头

    JSONP:

    浏览器script的src支持跨域访问,发了一个callback去服务器

    服务器接受callback 返回了一个函数的调用携带了数据回来

    浏览器接收到返回值当做js解析,执行代码

    【什么是同源策略】

    1、同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
    2、所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
    3、同源策略限制以下几种行为:
    (1)Cookie、LocalStorage 和 IndexDB 无法读取
    (2)DOM 和 Js对象无法获得
    (3)AJAX 请求不能发送

    浏览器采用同源策略,禁止页面加载或执行与自身来源不同的域的任何脚本。换句话说浏览器禁止的是来自不同源的"document"或脚本,对当前"document"读取或设置某些属性。

    情景: 

    比如一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。

    浏览器中有哪些不受同源限制呢?

    <script>、<img>、<iframe>、<link>这些包含 src 属性的标签可以加载跨域资源。但浏览器限制了JavaScript的权限使其不能读、写加载的内容。

    【解决方案】

    常见的解决方案分为三种,Nginx代理(前端实现),JSONP(前端实现),后台设置(后端实现)。

    1.Nginx代理(前端实现):

    案例说明:前端项目部署在8081端口,后端8081端口。

    nginx监听8081端口,将前端从nginx监听的端口8081请求过来的请求,代理转发到8080端口(8080为后端接口)


    1、JSONP

    前端实现:

    复制代码
    $.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp', // 请求方式为jsonp
    jsonpCallback: "onBack", // 自定义回调函数名
    data: {}
    });
    复制代码

    后端实现(SpringBoot)

    复制代码
    @ControllerAdvice(basePackages = "com.zkn.learnspringboot.web.controller")
    public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{
    
    public JsonpAdvice() {
    
    super("callback","jsonp");
    }
    }
    复制代码

    (1)前端发起请求时候,会加一个参数表示回调的函数 比如 callback=callback124 (callback 参数名也是可以自定义的,和后端协商好就行)
             后端返回的数据 callback124({“uid”:1})
    (2)参考:前端常见跨域解决方案(全)  https://segmentfault.com/a/1190000011145364 

    (3)JSONP的缺点

             JSONP只支持 GET 请求。

    (4)原理

             JSONP 是通过动态添加<script>标签来调用服务器的脚本(<script>含有src属性,src属性没有跨域限制);而 Ajax 是通过 XHR(XmlHttpRequest) 对象。

    2、跨域技术-CORS (CrossOrigin Resources Sharing,跨源资源共享)

         CORS是什么?

        CORS,是 HTML5 的一项特性,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。

        相对于 JSONP 这种解决方案来说,使用CORS,不需要要求服务器以指定格式返回数据(包装成JS脚本的格式:callback_func({ data }););CORS,只需要在服务器端做一些通用设置。

    前端实现:

    复制代码
    $.ajax({
    type: "post",
    url: 'http://192.168.45.152:8081/conference/user/bind',
    async: false, // 使用同步方式
    // 1 需要使用JSON.stringify 否则格式为 a=2&b=3&now=14...
    // 2 需要强制类型转换,否则格式为 {"a":"2","b":"3"}
    data: JSON.stringify({ 
    a: 1,
    b: '2',
    now: new Date().getTime() // 注意不要在此行增加逗号
    }),
    headers: {
    'Authentication':'xxxxxx'
    },
    contentType: "text/plain",
    dataType: "json",
    success: function(data) {
    console.log(data)
    } // 注意不要在此行增加逗号
    });
    复制代码


    后端实现(SpringBoot):

    复制代码
    @Configuration
    public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    //设置允许跨域的路径
    registry.addMapping("/**")
    //设置允许跨域请求的域名
    .allowedOrigins("*")
    //是否允许证书 不再默认开启
    .allowCredentials(true)
    //设置允许的方法
    .allowedMethods("GET", "POST")
    //跨域允许时间
    .maxAge(3600);
    
    }
    }
    复制代码

    CORS与JSONP的使用目的相同,但是比JSONP更强大。

    JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

    【跨域会话保持】

    对于前端来说,seesion字段是存在cookie中的。在跨域过程中,Cookie是默认不发送的。就算后端返回set-Cookie字段,前端也不会保存Cookie,更不会在下一次访问的时候发送到后端了。
    因此只要前端可以把cookie发送到后端,后端就可以根据cookie拿到seeion字段进行会话验证。
    进过重新对CORS的学习,只要通过3步,就可以让会话保持。

    1、在ajax中设置,withCredentials: true。
    默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。

    $.ajax({
    url: a_cross_domain_url,
    xhrFields: {
    withCredentials: true
    }
    });

    第二第三步,就是上面的服务端CORS的跨域技术

    服务端的 Access-Control-Allow-Credentials: true,代表服务器接受Cookie和HTTP认证信息。

    参考资料:

    (1)前后端分离-跨域会话如何保持?

    https://www.jianshu.com/p/26f877d2b315?tdsourcetag=s_pcqq_aiomsg

    (2)Session与Token认证机制 前后端分离下如何登录

    https://www.cnblogs.com/eret9616/p/9661314.html?tdsourcetag=s_pcqq_aiomsg

    (3)理解Cookie和Session机制

    https://www.cnblogs.com/andy-zhou/p/5360107.html

    转: https://blog.csdn.net/kevinxxw/article/details/90547184

     
  • 相关阅读:
    MAC配置DNS服务器
    真机IOS8.3以上的文件夹共享
    appium + python的环境配置_windows
    python 的时间与日期
    sublimetext 2 编译文件带input时 提示 EOFError: EOF when reading a line
    cmd无法输入中文解决方案
    配置python学习环境遇到的问题:[Decode error
    monkey初接触
    Android logcat输出中文乱码
    运行 命令框不记录打过的命令,重启后CMD里面是空的.上次打过的命令消失了.
  • 原文地址:https://www.cnblogs.com/chenxiaomeng/p/15559921.html
Copyright © 2020-2023  润新知