前端跨域解决方案

2023-11-14

同源政策

  1. 如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源。即便两个不同的域名指向同一个ip地址,也非同源。
    http://www.example.com:8080/dir/page.htmlhttp://www.example.com/page.html不跨域
    http:协议
    www:子域名
    example:主域名
    8080:端口号(http默认8080)
    同源策略限制以下几种行为:
  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM和JS对象无法获得
  • AJAX 请求不能发送

跨域

在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。

跨域报错
在这里插入图片描述

常见的跨域场景

URL 说明 是否允许通信
Website Domain Names, Online Stores & Hosting - Domain.coma.js Website Domain Names, Online Stores & Hosting - Domain.comb.js Website Domain Names, Online Stores & Hosting - Domain.comlab/c.js 同一域名,不同文件或路径 允许
http://www.domain.com:8000/a.js http://www.domain.com/b.js 同一域名,不同端口 不允许
http://www.domain.com/a.js https://www.domain.com/b.js 同一域名,不同协议 不允许
http://www.domain.com/a.js http://192.168.4.12/b.js 域名和域名对应相同ip 不允许
http://www.domain.com/a.js http://x.domain.com/b.js http://domain.com/c.js 主域相同,子域不同 不允许
http://www.domain1.com/a.js http://www.domain2.com/b.js 不同域名 不允许

跨域解决方案

1. JSONP跨域

jsonp的原理就是利用<script>标签没有跨域限制,通过<script>标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。

1). 原生JS实现

 <script>
    var script = document.createElement('script');
    script.type = 'text/javascript';
 
    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);
 
    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

服务端返回如下(返回时即执行全局函数):

handleCallback({"success": true, "user": "admin"})

2)jquery Ajax实现

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

3)Vue axios实现

this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

后端node.js代码

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
 
server.on('request', function(req, res) {
    var params = querystring.parse(req.url.split('?')[1]);
    var fn = params.callback;
 
    // jsonp返回设置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');
 
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

缺点

只支持get请求,不支持post请求。适用于加载不同域名的js、css、img等静态资源

2. 跨域资源共享(CORS)

CORS (Cross-Origin Resource Sharing,跨域资源共享), 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。

浏览器将CORS跨域请求分为简单请求和非简单请求。
只要同时满足一下两个条件,就属于简单请求
(1)使用下列方法之一:

  • head
  • get
  • post
    (2)请求的Heder是
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type: 只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain

不同时满足上面的两个条件,就属于非简单请求。浏览器对这两种的处理,是不一样的。

1) 简单请求

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

CORS请求设置的响应头字段,都以 Access-Control-开头:

  1. Access-Control-Allow-Origin:必选
    它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

  2. Access-Control-Allow-Credentials:可选
    它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

  3. Access-Control-Allow-Headers:可选
    CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

  4. Access-Control-Max-Age:预检请求的有效期。在此期间,无需再次发送预检请求。

2) 非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

预检请求
预检请求用的请求方法是OPTIONS,表示这个请求是用来询问的。请求头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,"预检"请求的头信息包括两个特殊字段。

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0..
  1. Access-Control-Request-Method:必选
    用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

  2. Access-Control-Request-Headers:可选
    该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

预检请求的回应
服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

HTTP回应中,除了关键的是Access-Control-Allow-Origin字段,其他CORS相关字段如下:

  1. Access-Control-Allow-Methods:必选
    它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

  2. Access-Control-Allow-Headers
    如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

  3. Access-Control-Allow-Credentials:可选
    该字段与简单请求时的含义相同。

  4. Access-Control-Max-Age:可选
    用来指定本次预检请求的有效期,单位为秒。

3) CORS跨域示例

  1. 前端设置
    原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
 
// 前端设置是否带cookie
xhr.withCredentials = true;
 
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
 
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

JQuery ajax:

$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    ...
});

2. 服务器端设置
nodejs代码

var http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    var postData = '';
 
    // 数据块接收中
    req.addListener('data', function(chunk) {
        postData += chunk;
    });
 
    // 数据接收完毕
    req.addListener('end', function() {
        postData = qs.parse(postData);
 
        // 跨域后台设置
        res.writeHead(200, {
            'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
            'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
            /* 
             * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
             * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
             */
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是让js无法读取cookie
        });
 
        res.write(JSON.stringify(postData));
        res.end();
    });
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

3. Vue的proxy跨域

通过vue-cli脚手架工具搭建项目,我们可以通过webpack为我们起一个本地服务器作为请求的代理对象

通过该服务器转发请求至目标服务器,得到结果再转发给前端,但是最终发布上线时如果web应用和接口服务器不在一起仍会跨域
在vue.config.js文件,新增以下代码

module.exports = {
    devServer: {
        host: '127.0.0.1',
        port: 8084,
        open: true,// vue项目启动时自动打开浏览器
        proxy: {
            '/api': { // '/api'是代理标识,用于告诉node,url前面是/api的就是使用代理的
                target: "http://xxx.xxx.xx.xx:8080", //目标地址,一般是指后台服务器地址
                changeOrigin: true, //是否跨域
                pathRewrite: { // pathRewrite 的作用是把实际Request Url中的'/api'用""代替
                    '^/api': "" 
                }
            }
        }
    }
}

通过axios发送请求中,配置请求的根路径

const http = axios.create({
  timeout: 1000 * 1000000,
  withCredentials: true,
  BASE_URL: '/api'
  headers: {
     'Content-Type': 'application/json; charset=utf-8'
   }
})

4. Node代理服务器解决跨域

因为同源策略是浏览器限制的,所以服务端请求服务器是不受浏览器同源策略的限制的,因此可以搭建一个自己的node服务器来代理访问服务器。

大概的流程就是:我们在客户端请求自己的node代理服务器,然后在node代理服务器中转发客户端的请求访问服务器,服务器处理请求后给代理服务器响应数据,然后在代理服务器中把服务器响应的数据再返回给客户端。客户端和自己搭建的代理服务器之间也存在跨域问题,所以需要在代理服务器中设置CORS。
基本的工作流程如下:
在这里插入图片描述

前端代码

<!-- 引入axios发送请求 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    // 简单封装一个axios向代理服务器发送请求
    function proxyAxios(data) {
        return axios({
            url: 'http://localhost:8081/proxyApi', // 请求自己搭建的node代理服务器的地址
            method: 'POST',
            headers: { 'content-type': 'application/x-www-form-urlencoded' },
            data
        })
    }

    // 使用node代理服务器向服务器发送请求
    proxyAxios({
        url: 'https://class.imooc.com/getadver',// 需要代理访问真实服务器的url
        method: 'GET',
    }).then(res => {
        console.log('res:', res)
    }).catch(err => {
        console.log(err)
    })
</script>

node服务器代码如下:

/**通过nodeJS搭建自己的代理服务器来解决跨域问题 */
const axios = require('axios')
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
// 使用第三方插件
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())

// 监听post请求,处理代理接口
app.post('/proxyApi', (req, res) => {
    const {body} = req
	// 获取post请求的请求参数
    let reqParams = {}
	  for(const key in body) {
        reqParams = JSON.parse(key) // 获取到请求参数
    }

    // 设置响应头
    // 代理服务器设置CORS,允许跨域访问
    res.setHeader('Access-Control-Allow-Origin', '*') 
    res.setHeader('Access-Control-Allow-Methods', '*') // 允许所有的请求方式

    const {url, method = "GET", ...resConfig} = reqParams || {}
     // node代理请求服务器
     axios({
        url,
        method,
        ...resConfig
      }).then(result => {
        const {status, headers, data} = result
        res.status(status)
        res.setHeader('content-type', headers['content-type'])
        res.end(JSON.stringify(data)) // 给客户端返回数据
      }).catch(err => {
        res.end(JSON.stringify(err))
      })
})

// 监听请求
app.listen(8081, () => {
	console.log('服务启动成功,在8081端口监听请求....')
})

5. nginx代理跨域

nginx代理跨域,实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段。

1)nginx配置解决iconfont跨域

浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。

location / {
  add_header Access-Control-Allow-Origin *;
}

2)nginx反向代理解决跨域

跨域问题:同源策略仅是针对浏览器的安全策略。服务器端调用HTTP接口只是使用HTTP协议,不需要同源策略,也就不存在跨域问题。

nginx通过反向代理解决跨域也是利用了服务器请求服务器不受浏览器同源策略的限制实现的。

实现思路:客户端请求nginx服务器,在nginx.conf配置文件中配置server监听客户端的请求,然后把location匹配的路径代理到真实的服务器,服务器处理请求后返回数据,nginx再把数据给客户端返回。大致流程如下:

在这里插入图片描述
nginx.conf配置文件中的配置:

server {
    listen  8082;    //配置监听客户端的请求端口
    server_name  localhost;    //访问的域名
    //localtion配置的是将匹配的路径代理到proxy——pass设置的真实服务器上
    location /api {
        proxy_pass   http://localhost:8081;  //proxy_pass设置真实访问的服务器地址
        // 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  //当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Methods "GET,POST,PUT,OPTIONS";
    }
}

前端代码:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    axios({
        url: 'http://localhost:8082/api', // 向nginx服务器发送请求
        method: 'get'
    }).then(res => {
        console.log('res:', res)
    }).catch(err => {
        console.log('err:', err)
    })
</script>

最终要访问的服务端代码如下:

const express = require('express')
const app = express()

app.get('/api', (req, res) => {
  const user = { // 模拟返回数据
    id: 1, 
    name: 'zhangsan',
    age: 12
  }
  res.end(JSON.stringify(user))
})

// 监听请求
app.listen(8081, () => {
	console.log('服务启动成功,在8081端口监听请求....')
})

nginx反向代理方式和node中间件代理方式的原理其实差不多,都是利用了服务器和服务器之间通信不受浏览器的同源策略的限制,但是node代理方式相对复杂一些,还要自己搭建一个node服务器,而用nginx只需要修改nginx.conf配置文件即可解决跨域问题。

6. postMessage方式

window.postMessage() 方法可以安全地实现跨源通信,此方法一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。,它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

用法:postMessage(data,origin)方法接受两个参数:

  • data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
  • origin: 协议+主机+端口号,也可以设置为*,表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

1)a.html:(http://www.domain1.com/a.html)

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // 向domain2传送跨域数据
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
    };
 
    // 接受domain2返回数据
    window.addEventListener('message', function(e) {
        alert('data from domain2 ---> ' + e.data);
    }, false);
</script>

2)b.html:(http://www.domain2.com/b.html)

<script>
    // 接收domain1的数据
    window.addEventListener('message', function(e) {
        alert('data from domain1 ---> ' + e.data);
 		const {data, origin, source} = e
        var data = JSON.parse(data);
        if(origin !== 'http://www.domain1.com') return
        if (data) {
            data.number = 16;
 
            // 处理后再发回domain1
            window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
        }

    }, false);
</script>

使用postMessage向其它窗口发送数据的时候需要注意的就是,应该始终指定精确的目标 origin,而不是*,使用window监听message事件,接收其他网站发送的 message时,请始终使用 origin 和 source 属性验证发件人的身份。

7. WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

前端代码

<div>user input:<input type="text"></div>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080');
 
// 连接成功处理
socket.on('connect', function() {
    // 监听服务端消息
    socket.on('message', function(msg) {
        console.log('data from server: ---> ' + msg); 
    });
 
    // 监听服务端关闭
    socket.on('disconnect', function() { 
        console.log('Server socket has closed.'); 
    });
});
 
document.getElementsByTagName('input')[0].onblur = function() {
    socket.send(this.value);
};
</script>

Nodejs socket后台

var http = require('http');
var socket = require('socket.io');
 
// 启http服务
var server = http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-type': 'text/html'
    });
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');
 
// 监听socket连接
socket.listen(server).on('connection', function(client) {
    // 接收信息
    client.on('message', function(msg) {
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    });
 
    // 断开处理
    client.on('disconnect', function() {
        console.log('Client socket has closed.'); 
    });
});

8. iframe系列

  1. document.domain +iframe跨域:两个页面都通过js强制设置document.domain为基础主域,实现同域
  2. locatin.hash + iframe跨域:a 与b跨域相互通信,通过中间页c来实现,三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
  3. window. name + iframe跨域:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。
    详见:9种常见的前端跨域解决方案(详解)

小结

以上就是常见的跨域解决方案,jsonp(只支持get请求,支持老的IE浏览器)适合加载不同域名的js、css,img等静态资源;
  CORS(支持所有类型的HTTP请求,但浏览器IE10以下不支持)适合做ajax各种跨域请求;
  Vue框架的proxy代理、Nginx代理跨域和nodejs中间件跨域原理都相似,都是搭建一个服务器,直接在服务器端请求HTTP接口,这适合前后端分离的前端项目调后端接口。
  document.domain+iframe适合主域名相同,子域名不同的跨域请求。postMessagewebsocket都是HTML5新特性,兼容性不是很好,只适用于主流浏览器和IE10+。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

前端跨域解决方案 的相关文章

随机推荐

  • Python——os.mkdir()在指定路径下创建文件夹 + 路径的连接理解

    引子 我在用路径连接函数 os path join 时发现 其连接的各级目录必须首先存在 才可以连接 也即是说连接的各文件夹必须首先存在 因为个各层级的目录以文件夹的形式表现出来 基于此 我开始研究如何先在指定路径下创建文件夹 1 在指定路
  • linux批量替换文件夹中所有文件内容

    记录一下 以防自己忘了 替换单个文件 sed i s 旧字符串 新字符串 g 文件名 替换整行 sed i 旧字符串 c 新字符串 文件名 替换文件夹中所有文件内容 sed i s 旧字符串 新字符串 g grep 旧字符串 rl 目录
  • MIPI协议之CSI2和DPHY

    目录 1 概论 2 CSI2协议 2 1 CSI 2数据帧格式 3 D PHY 3 1 数据通道模块的工作流程图 3 2 数据通道模块状态图 1 概论 MIPI协议 Moblie Industry Process Interface 移动行
  • Android 如何修改按钮默认的讨厌的蓝紫色

    1 在设置好按钮背景时 发现钮颜色始终没有改变 2 原来是默认主题themes的问题 在这里修改主题即可 3 找到 res values themes themes xml 双击打开themes xml文件 4 修改parent内容为 Th
  • Linux编程语言glob函数,linux glob函数man页与实例

    Linux Programmer s Manual NAME glob globfree find pathnames matching a pattern free memory from glob SYNOPSIS include in
  • 如何选择IO调度器

    概述 不格文学网 m vbuge com 由于对multi quque的IO调度算法不太熟悉 为了避免误人子弟 本文暂时只会介绍如何选择single queue的IO调度算法 等将来对multi queue有充分认识后再补充 如果不清楚什么
  • redhat激活管理

    redhat激活管理 redhat激活管理常用命令 查看 激活 删除订阅 刷新 redhat激活管理常用命令 https blog csdn net xixihahalelehehe article details 79108442 查看
  • pyqt5_1 Qt Designer组件讲解

    一 布局 Vertical Layout 纵向布局 Horizontal Layout 横向布局 Grid Layout 栅格布局 QGridLayout 网格布局 是将窗口分割成行和列的网络来进行排列 Form Layout 表单布局 在
  • 关于U盘中“文件夹EXE病毒”的解决方案

    笔者在使用U盘时 无意之间发现U盘所有文件的后缀名均变为 exe 经过查询相关资料 确认这是一种病毒 文件夹EXE病毒 一 简介 木马名称 Worm Win32 AutoRun soq 当把U盘插入到一台电脑后 U盘内生成了以原文件夹名字命
  • Ubuntu 安装 Oracle JDK

    1 写在前面 本文主要介绍如何在Ubuntu系统下安装Oracle JDK 2 环境准备 2 1 下载JDK 2 1 1 浏览器下载安装包 进入虚拟机浏览器访问官网地址 http www oracle com technetwork jav
  • 一分钟带你快速认识S参数

    S 参数是SI与RF领域工程师必备的基础知识 大家很容易从网络或书本上找到S Y Z参数的说明 但即使如此 在相关领域打滚多年的人 仍然可能还是会被一些问题困扰着 你懂S参数吗 不懂的话 那么请继续往下看 S参数简介 S参数 也就是散射参数
  • GitLab的使用 和 Git 、 Github、Gitlab的区别

    一 git github gitlab的区别 百度相关内容得到的理解 二 git最基本作用 版本控制 三 有集成了git的GIT安装包 github和gitlab都使用git该版本控制系统 来实现对代码的管理 所以 原先怎么用git操作gi
  • obs窗口捕获不到ppt白屏_如何用obs进行电脑直播,学会这篇,直播不再难

    很多人想在头条或者西瓜视频直播 除了用手机直播外 还可以用电脑进行直播 只要用obs进行简单设置即可达到要求 可以直播ppt 直播ps等 1 下载并安装好obs软件 点击文件 设置 在设置的窗口中 找到输出 一般输出的设置默认就好 无需更改
  • 微信浮窗是不是服务器保存,微信浮窗,真能解决小程序留存难题吗?

    小程序浮窗 到底有多大能量 作者丨Suvi 上个月 微信更新了7 0 5版本 对浮窗功能做了全新升级 支持最多同时添加5个项目 不含QQ音乐 并首次支持添加小程序 新版浮窗一上线 便被寄予厚望 各方将之解读为挽救公众号阅读量 提高小程序留存
  • 【8】测试用例设计-边界值法

    对于软件来说 错误经常发生在输入或输出值的关键点 边界值分析法是对软件的输入或输出边界进行测试的一种方法 它的所有测试用例都是在等价类的边界处设计 边界值分析需要选择一个或多个元素 以便等价类的每个边界都经过一次测试 与仅仅关注输入条件 输
  • QT+CUDA混合编程BUG(一)

    QT CUDA混合编程BUG 一 在QT中进行CUDA编程 CUDA库与其他外部库冲突 debug失败 问题描述 在QT中进行CUDA编程 单独使用CUDA编程时并未出现难以解决的问题 但当我讲CUDA处理的部分 加入已搭建完毕一项较大的Q
  • LeetCode第 292 题:Nim游戏(C++)

    292 Nim 游戏 力扣 LeetCode 剩下4块的时候 如果轮到你 那么你必输 先简单推一下 如果第n块的时候轮到你 n 5 必胜 拿1块 n 6 必胜 拿2块 n 7 必胜 拿3块 n 8 必败 无论我拿几块 对方都可以将我逼到4的
  • 基于Lasagne实现限制玻尔兹曼机(RBM)

    RBM理论部分大家看懂这个图片就差不多了 Lasagne写代码首先要确定层与层 RBM 正向反向过程可以分别当作一个层 权值矩阵互为转置即可 代码 coding utf 8 data format is bc01 written by Ph
  • 【Shell编程】Shell中Bash变量-用户自定义变量

    目录 系列文章 Bash变量 用户自定义变量 变量的命名规则 变量分类 本地变量 实例 系列文章 Shell编程 Shell基本概述与脚本执行方式 Shell编程 Shell中Bash基本功能 Bash变量 用户自定义变量 变量的命名规则
  • 前端跨域解决方案

    目录 同源政策 跨域 常见的跨域场景 跨域解决方案 1 JSONP跨域 1 原生JS实现 2 jquery Ajax实现 3 Vue axios实现 后端node js代码 2 跨域资源共享 CORS 1 简单请求 2 非简单请求 3 CO