区块链安全:从web3.0到数字货币

news2024/11/28 8:51:43

互联网发展的三个阶段

web1.0

静态页面,内容只能供用户去阅读,类似于在网络上读报纸或者看书。

web2.0

动态互联网,实现用户之间的互动,比如twitter,facebook,titok等。

web2.0中厂商用免费或极低的成本吸引用户,通过获取到用户的信息来推流广告从而获得利润。

打个比方就是 厂商在一片地上种了很多草,吸引羊来吃,趁着羊吃草的功夫把羊身上的毛薅下来拿去卖钱,而羊自己并不在意这些毛,可以说是一种双向互利的方式。

web3.0

web3.0是一个很模糊的概念,随着区块链技术的发展,基于区块链的web3.0诞生。

接着用上面的例子来说,随着web2.0的发展壮大,稀缺的不再是草,而是羊毛,也就是用户身上的数据。那么羊毛的重要性愈加突出,所以提出web3.0的概念,也就是拥有自己的一片空间,别人无论如何都无法修改,也就是将羊毛(数据)存放在了一个非常安全的地方中,相比于web2.0,不但实现了动态的交互,也实现了数据的“拥有”。

web3的概念非常模糊,可以说是一个大方向,按照我个人的理解可以说是在互联网创造了一个虚拟的世界,这个虚拟的世界拥有和现实世界一样的货币交易系统以及其他体系,能够自主维持运转的这样一个“虚拟生态系统”,而这个生态系统的生存法则就是“去中心化”。

什么是去中心化?

比如现在市面上的app都由一个厂家负责,厂商可以随意删除控制用户数据,形成了以厂商为中心的服务体系,去中心化就是没有中心厂商作为核心,而是所有用户形成一个能够自力更生的体系。

密码货币

随着web2.0发展,数字货币使用越来越多,而在区块链技术的支持下,数字货币也出现了全新的存在形式,去中心化的密码货币,世界上第一种密码货币就是比特币。像纸币有防伪印一样,密码货币通过密码学的散列计算出的hash值并且和智能合约进行绑定,密码货币基于去中心化的机制,与依赖中心监管体系的银行金融系统相对。之后出现的数种密码货币被创造,它们通常被称为altcoins。

区块链

区块链的防篡改机制
一个区块中储存了三样东西:数据,前一个区块的hash值,自身的hash值(由数据和前一区块的哈希值共同决定),如果要更改某一区块的内容,那么该区块(a区块)的hash值就会改变,下一区块(b区块)储存的a区块的hash值无法对应a区块当前哈希值,那么这两个区块间的链接就会断开。

如果想要篡改某一区块的数据,我们就要将这一区块以及后续所有区块的hash值进行重算,比如一条区块链里面有abcde五个区块,当我们篡改了b区块的数据,那么我们就要带着b区块的新hash值和c区块的数据重新计算出c区块的新hash值,然后再带着c区块的新hash值和d区块的数据重新计算d区块的新hash值,再带着d区块的新hash值和e区块的数据重新计算e区块的hash值……………………其实在重新计算某一区块的hash值的过程也就相当于创造了一个新的区块,因此篡改一个区块以及后续区块所需的时间取决于创造一个区块所需要的时间。

这个看起来对算力要求似乎非常庞大,但是现代计算机其实是可以做到这一点的,如果我们有一台超大算力的计算机,那么是不是轻松就可以改变区块链的内容了?为了防止这种情况的出现,区块链加入了工作量证明机制(proof of work)简称 pow

我们用游戏举例说明一下pow,我们刚才说到用超大算力计算机来篡改区块链,这就好比你拿着满级神装在新手村乱杀,区块链是不允许这种情况出现的,因此它会上调怪物属性,也就是会增加创造一个区块所需的难度,使每一新区块被创造时都保持在十分钟左右(当然这个时间是可以更改的),因此即使是一台超高算力的计算机想要篡改一个区块所需的时间仍然是

创造一个区块的时间✖️n min

那我们所说的挖矿是什么呢?上面提到的情况是想要篡改区块中的数据,那么我没有恶意,我只是单纯的创造区块去给自己或者他人使用,这个创造区块的过程牺牲了我电脑的算力和一些其他资源,所以作为补偿,创建区块的人会得到密码货币的奖励,这就是我们所说的挖矿。

区块链的点对点网络结构

在传统的web服务中,传统的链接对象基本都是客户端和服务端,众多客户端访问一个服务端来进行交互,而在区块链的点对点网络结构(peer to peer)中,不再有客户端与服务端的概念,每一个节点间相互平等,并且包含完整的区块链数据存储,也就是说每一个节点中都储存了整个区块链网络中的所有信息,这样即使一个节点出现故障,其他所有节点也在帮他记录信息,这些记录了所有节点区块链的节点叫做全节点,当然也有只储存了自己信息的轻节点,比如区块链用来储存转账记录,那么每一节点都储存了所有节点之间的转账记录,每一节点储存的内容也是相同的,如果某一节点与其他节点出现差异,那么该节点或许就有被篡改过的可能了,但是被篡改几乎是不可能发生的,原因看下面。

点对点网络结构下的所有节点拥有判断区块是否被篡改的能力,当一个新区块想要加入某一节点的区块链时,该节点会向其他所有节点进行广播,所有的节点进行判断,如果50%以上的节点都认为该区块没有被篡改,那么这个区块就可以成功的加入区块链当中,反言之如果想要篡改某一区块的数据,你首先要将这一区块后的所有哈希重新计算,并且还要更改超过百分之五十节点的这一区块后的所有区块的哈希,那么就要拥有超过全网50%以上的算力才可以,这付出的代价是相当高的,这就是区块链网络系统的少数服从多数原则。

DAPP

Dapp 是什么?

APP (Application) 指的是手机里的应用程序,像是微信、微博、抖音…等都是日常生活中常会使用到的 App。

而 Dapp 的全名为去中心化应用程序(Decentralized Application),是建立在区块链系统网络上,所提供的服务都具有公开透明、不可篡改的特性。
【----帮助网安学习,以下所有学习资料免费领!加@v~:yj009991,备注“ csdn ”获取!】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

以下是 Dapp 所具有的要素:

  • 代码开源:程序代码皆公开透明,任何人都可以查阅及审核,避免项目方说到没做到。
  • 分布式帐本:降低数据遗失的风险,且没有任何其他第三方有权能够窜改数据。
  • 数据所有权:除本人(私钥持有者)外,任何人皆无法动用该帐号的数据。

为什么 Dapp 会崛起?

事实上,App 都是中心化的应用服务,用户所使用的数据都会存储在单一服务器系统里,代表公司能掌控用户的所有数据,但相关问题也随之浮出水面。

数据所有权归属问题

用户在 App 上的个人资料、搜索浏览纪录等信息都会存储在中心化系统的服务器里,这也意味着软件公司能够借由这些数据来营利。

也导致像是微博、抖音等企业,能透过搜集的用户数据来投放广告,并借此获利。等于企业能用你的信息来赚钱,但你却分不到任何好处,甚至还可能受到影响(例如被疯狂投放广告、或个人资料被平台外泄)。

另外,传统手游的游戏道具、帐号数据也都属于公司所有,一旦宣布停止营运,这些资产也会随着官方服务器关闭而消失。

但在 Dapp 中,你的游戏道具、帐号都会以 NFT 形式储存在链上,因此只要区块链不倒,你就能持续拥有这些资产。换句话说,Dapp 能够让数据的所有权回归到用户身上。额外提醒,虽然你仍拥有这些资产,但可能会因为游戏已经关闭,导致这些资产的现值趋近于零,你能保有的仍以回忆居多。

过度中心化

App 是由中心化服务器来进行管理,因此企业有时可以专断独行,但用户却没有任何反制的手段:例如可以随意植入广告,或是删除用户的内容、帐号。

而 Dapp 的数据都存在区块链上,因此项目方没办法任意删除用户资料,目前也没有任何广告植入的问题(但不确定未来是否会有项目开始植入广告)。

由于上述几点原因,也让许多人开始对传统的 App 感到不满,于是就有人打算通过区块链“去中心化”的特性来研发能解决上述问题的 App,于是 Dapp 就此诞生。

不过同时也要注意,不是每个 Dapp 都一定符合公开、去中心化的规范,例如 Opensea 就能下架用户的 NFT 和限制用户登陆。

Dapp 与 App 的差异

App 的应用服务是使用中心化服务器,代表软件公司必须要承担存储用户的数据量的营运成本,否则将无法持续地运行。

例如抖音服务器的成本就百万以上,因此必须想办法创造各种营收管道来支持各项支出,像是通过大数据将广告推广到潜在用户面前,借此吸引更多广告商进驻。

而 Dapp 是建立在区块链上,用户在链上进行交易、换币等行为时,是需要自行负担手续费(Gas 费)的,也就代表开发商的运营成本会比传统 App 来得更低(不过有些开发商为了吸引用户,会帮用户负担使用时的手续费)。

DappApp
服务器去中心化中心化
隐私性有(区块链匿名性)无(还可能被外泄)
营运成本用户共同负担(或开发商负担)开发商负担
平台获利来源智能合约(链上手续费)广告商或用户消费
数据所有权用户开发商
平台控制权开发商或是 DAO 治理开发商
系统区块链Android、iOS
代码是否开源代码皆公开,可供人参考代码为公司机密,擅用者可能会吃上官司

智能合约

智能合约,是一段写在区块链上的代码,一旦某个事件触发合约中的条款,代码即自动执行。也就是说,满足条件就执行,不需要人为操控,类似于传统web的后端代码。

简单区块链实现

我们用Javascript来手写一个建议的区块链出来,其实和写一个链表很像:

const sha256 = require('crypto-js/sha256')
Date = new Date()

class block{
    constructor(data,time,previousHash) {
        this.data = data
        this.time = time
        this.previousHash = previousHash
        this.myHash = this.currHash()
    }
    currHash() {
        return sha256(this.data + this.time + this.previousHash).toString()
    }
}

class blockCahin{
    constructor()
    {
        this.chain = [this.createBlockchain()];
    }
    createBlockchain()
    {
        return new block("Genesisblock",Date.toLocaleString(),0o0000000)
    }
    getLatestblock()
    {
        return this.chain[this.chain.length - 1]
    }
    addBlock(newBlock)
    {
        newBlock.previousHash = this.getLatestblock().myHash
        newBlock.myHash = newBlock.currHash()
        this.chain.push(newBlock)
    }
}

BlockChain = new blockCahin()
BlockChain.addBlock(new block("this is a test",Date.toLocaleDateString(),"anything"))
console.log(BlockChain)

在这里插入图片描述

接下来我们用代码实现一下简易的POW:

const sha256 = require("crypto-js/sha256")
function proofOfwork(){
    let seed = "y1zh3e7"
    let x = 1               // x为自增变量
    while (true){
        if(sha256(seed + x).toString().substring(0,4) != "0000") // 定义难度,比如我现在要求通过不断自增x去计算seed+x的哈希值
        {                                                        // 当哈希值前四位都为0000时则代表成功 如果想提高难度我们就可以让前x位为xxxx
            x += 1
        }else{
            console.log(sha256(seed + x).toString())
            break
        }
    }
    console.log(x)                                              // 输出计算多少次后成功
}

proofOfwork()

实现防篡改机制:

/***********************************************
验证区块链防篡改需要检测两项:                                    
 1.重新计算区块的hash值,判断与区块中储存的hash是否相同 
 2.判断当前区块的previousHash是否和上一区块的hash相同 
 ***********************************************/
function validateBlock(validBlockchain){
    if (validBlockchain.chain.length == 1)
    {
        if(validBlockchain.chain[0].myHash != validBlockchain.calcHash())
        {
            console.log("数据篡改")
            return false
        }
    }else {
        for (let i=1; i<=validBlockchain.chain.length-1; i++)
        {
            if(validBlockchain.chain[i].myHash != validBlockchain.chain[i].calcHash())
            {
                console.log("数据篡改")
                return false
            }
            if (validBlockchain.chain[i].previousHash != validBlockchain.chain[i-1].myHash)
            {
                console.log("前后区块链断裂")
                return false
            }
        }
    }
    console.log("数据无篡改且区块链结构完整")
    return true
}

将完整的POW整合到区块链当中并实现挖矿功能,最终实现的完整区块链:

const sha256 = require('crypto-js/sha256')
Date = new Date()

class block{
    constructor(data,time,previousHash) {
        this.data = data
        this.time = time
        this.nonce = 1
        this.previousHash = previousHash
        this.myHash = this.calcHash()
    }
    calcHash() {
        return sha256(this.data + this.time + this.previousHash + this.nonce).toString()
    }
    /**  **/
    getAnswer(difficulty){
        let answer = ""
        for(let i=0; i<difficulty; i++)
        {
            answer += "0"
        }
        console.log(answer)
        return answer
    }
   /** 引入挖矿功能 **/
    mine(difficulty){
        let answer = this.getAnswer(difficulty)
        let Hash = this.calcHash()
       while(true){
            if (Hash.substring(0,difficulty) != answer)
            {
                this.nonce++
                Hash = this.calcHash()
            }else{
                break
            }
       }
       console.log("mine successful!")
       console.log(this.nonce)
       return Hash
    }
}

class blockCahin{
    constructor()
    {
        this.chain = [this.createBlockchain()]
        this.difficulty = 5
    }
    createBlockchain()
    {
        return new block("Genesisblock",Date.toLocaleString(),0o0000000)
    }
    getLatestblock()
    {
        return this.chain[this.chain.length - 1]
    }
    addBlock(newBlock)
    {
        newBlock.previousHash = this.getLatestblock().myHash
        newBlock.myHash = newBlock.mine(this.difficulty)
        this.chain.push(newBlock)
    }
}

/***********************************************
验证区块链防篡改需要检测两项:
 1.重新计算区块的hash值,判断与区块中储存的hash是否相同
 2.判断当前区块的previousHash是否和上一区块的hash相同
 ***********************************************/
function validateBlock(validBlockchain){
    if (validBlockchain.chain.length == 1)
    {
        if(validBlockchain.chain[0].myHash != validBlockchain.calcHash())
        {
            console.log("数据篡改")
            return false
        }
    }else {
        for (let i=1; i<=validBlockchain.chain.length-1; i++)
        {
            if(validBlockchain.chain[i].myHash != validBlockchain.chain[i].calcHash())
            {
                console.log("数据篡改")
                return false
            }
            if (validBlockchain.chain[i].previousHash != validBlockchain.chain[i-1].myHash)
            {
                console.log("前后区块链断裂")
                return false
            }
        }
    }
    console.log("数据无篡改且区块链结构完整")
    return true
}

BlockChain = new blockCahin()
BlockChain.addBlock(new block("this is a test",Date.toLocaleDateString(),"anything"))
// console.log(BlockChain)
// BlockChain.chain[1].data = "数据篡改"
// BlockChain.chain[0].myHash = "0012343566688"
// console.log(validateBlock(BlockChain))

数字货币的简单实现

创建自己的数字货币

首先我们要新建一个Transaction类来进行转账记录:

class Transaction{
    constructor(from, to , amount) {
        this.from = from
        this.to = to
        this.amount = amount
    }
}

更改区块中data的含义,此时要记录的是转账信息transaction,并且由于transaction是一个对象,因此在参与计算哈希时要转为字符串(这里将时间改为了Date.now,这样在区块创造时就记录了这笔转账记录的时间):

class Block{
    constructor(transaction,previousHash) {
        this.transactions = transaction
        this.time = Date.now()
        this.nonce = 1
        this.previousHash = previousHash
        this.myHash = this.calcHash()
    }
    // 计算hash时要将data转换为字符串类型,此时的data是一个transaction
    calcHash() {
        return sha256(JSON.stringify(this.transactions) + this.time + this.previousHash + this.nonce).toString()
    }

上面说到奖励货币的发放是通过转账的方式实现的,所以我们在链上实现逻辑:

class blockChain{
    constructor()
    {
        this.chain = [this.createBlockchain()]
        this.difficulty = 5
        this.transactionPool = []  //挖矿成功的转账信息
        this.mineReward = 50       //每次挖矿成功的奖励货币数
    }
mineTransaction(minerAddress)
    {
        const minerRewardTransaction =  new Transaction('', minerAddress, this.mineReward)
        this.transactionPool.push(minerRewardTransaction)
    }

之前我们是在外部传入一个区块,在整个货币系统的实现后区块应该是在挖矿时在区块链内部产生的,修改代码:

//将Transaction添加到Transaction Pool中
    addTransaction(Transaction)
    {
        this.transactionPool.push(Transaction)
    }
		
		mineTransaction(minerAddress)
    {
        const minerRewardTransaction =  new Transaction('', minerAddress, this.mineReward)
        this.transactionPool.push(minerRewardTransaction)

        //挖矿
        /********************************************************
         * 这里新区块记录了整个区块链的转账信息,但在实际情况中区块的存储
         * 容量是有限制的,所以在挖矿时记录的转账记录会选择手续费最高的transaction
         * 我们这里先不考虑这种情况
         *******************************************************/
        const newBlock = new Block(this.transactionPool,this.getLatestBlock().myHash)
        newBlock.mine()

        //添加到区块链,并清空Transaction Pool
        this.chain.push(newBlock)
        this.transactionPool = []
    }

整个写好的数字代币:

const sha256 = require('crypto-js/sha256')

class Transaction{
    constructor(from, to , amount) {
        this.from = from
        this.to = to
        this.amount = amount
    }
}
class Block{
    constructor(transaction,previousHash) {
        this.transactions = transaction
        this.time = Date.now()
        this.nonce = 1
        this.previousHash = previousHash
        this.myHash = this.calcHash()
    }
    // 计算hash时要将data转换为字符串类型,此时的data是一个transaction
    calcHash() {
        return sha256(JSON.stringify(this.transactions) + this.time + this.previousHash + this.nonce).toString()
    }
    /** 获取相应难度hash **/
    getAnswer(difficulty){
        let answer = ""
        for(let i=0; i<difficulty; i++)
        {
            answer += "0"
        }
        return answer
    }
   /** 引入挖矿功能 **/
    mine(difficulty){
        let answer = this.getAnswer(difficulty)
        let Hash = this.calcHash()
       while(true){
            if (Hash.substring(0,difficulty) != answer)
            {
                this.nonce++
                Hash = this.calcHash()
            }else{
                break
            }
       }
       console.log("mine successful!\n")
       console.log("计算"+this.nonce+"次后挖矿成功,answer为"+Hash)
       return Hash
    }
}

class blockChain{
    constructor()
    {
        this.chain = [this.createBlockchain()]
        this.difficulty = 4
        this.transactionPool = []  //挖矿成功的转账信息
        this.mineReward = 50       //每次挖矿成功的奖励货币数
    }
    createBlockchain()
    {
        return new Block("Genesisblock",null)
    }
    getLatestBlock()
    {
        return this.chain[this.chain.length - 1]
    }
    //将Transaction添加到Transaction Pool中
    addTransaction(Transaction)
    {
        this.transactionPool.push(Transaction)
    }
    mineTransaction(minerAddress)
    {
        const minerRewardTransaction =  new Transaction('', minerAddress, this.mineReward)
        this.transactionPool.push(minerRewardTransaction)

        //挖矿
        /********************************************************
         * 这里新区块记录了整个区块链的转账信息,但在实际情况中区块的存储
         * 容量是有限制的,所以在挖矿时记录的转账记录会选择手续费最高的transaction
         * 我们这里先不考虑这种情况
         *******************************************************/
        const newBlock = new Block(this.transactionPool,this.getLatestBlock().myHash)
        newBlock.mine(this.difficulty)

        //添加到区块链,并清空Transaction Pool
        this.chain.push(newBlock)
        this.transactionPool = []
    }

}

/***********************************************
验证区块链防篡改需要检测两项:
 1.重新计算区块的hash值,判断与区块中储存的hash是否相同
 2.判断当前区块的previousHash是否和上一区块的hash相同
 ***********************************************/
function validateBlock(validBlockchain){
    if (validBlockchain.chain.length == 1)
    {
        if(validBlockchain.chain[0].myHash != validBlockchain.calcHash())
        {
            console.log("数据篡改")
            return false
        }
    }else {
        for (let i=1; i<=validBlockchain.chain.length-1; i++)
        {
            if(validBlockchain.chain[i].myHash != validBlockchain.chain[i].calcHash())
            {
                console.log("数据篡改")
                return false
            }
            if (validBlockchain.chain[i].previousHash != validBlockchain.chain[i-1].myHash)
            {
                console.log("前后区块链断裂")
                return false
            }
        }
    }
    console.log("数据无篡改且区块链结构完整")
    return true
}

Y1Coin = new blockChain()
const Transaction1 = new Transaction('add1', 'add2', 20)
const Transaction2 = new Transaction('add1', 'add2', 5)
Y1Coin.addTransaction(Transaction1)
Y1Coin.addTransaction(Transaction2)
Y1Coin.mineTransaction("add3")
console.log(Y1Coin)
console.log(Y1Coin.chain[1].transactions)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/331520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于UDP/TCP实现客户端服务器的网络通信程序

目录&#xff1a;前言基于UDP实现客户端服务器的网络通信程序基于TCP实现客户端服务器的网络通信程序前言网络编程的核心是Socket API&#xff0c;它是操作系统给应用程序提供的网络编程API&#xff0c;可以认为是socket api是和传输层密切相关的。在传输层里面&#xff0c;提供…

leetcode刷题---递归思想

leetcode刷题---递归思想&#xff09;1.1 递归介绍1.2 基本步骤1.3 代表题目1.3.1 入门题---青蛙跳1.3.2.1 初级题226.翻转二叉树112.路径总和1.3.3 中级题---汉诺塔问题1.3.4 进阶题---细胞分裂1.1 递归介绍 如果在函数中存在着调用函数本身的情况&#xff0c;这种现象就叫递…

java Resource

参看本文前 你要先了解 spring中的 Autowired和Qualifier 注解 如果之前没有接触过 可以查看我的文章 java spring 根据注解方式按(类型/名称)注入Bean 然后 创建一个java项目 引入spring注解方式 所需要的包 然后 在src下创建包 我们这里直接叫 Bean 在Bean下创建包 叫UserD…

【GIC】处理中断

目录 一、当中断变为pending时发生了什么&#xff1f; 二、中断响应 三、虚假的中断 四、运行优先级&抢占 五、结束中断 六、检查系统的当前状态 6.1最高优先级等待中断和运行优先级 6.2单个INTID的状态 一、当中断变为pending时发生了什么&#xff1f; 前面的文章…

0207 事件

事件监听事件监听版本事件类型事件概念事件在编程时系统内发生的动作或者发生的事情例子点击按钮鼠标经过拖拽鼠标事件监听&#xff08;注册事件&#xff0c;绑定事件&#xff09;让程序员检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响应…

PHP立体安全:一网打尽攻击向量

PHP立体安全&#xff1a;一网打尽攻击向量 所谓攻击向量&#xff0c;就是指黑传递有效负载或恶意结果而可以访问计算机或网络服务器的路径或方法。 PHP的安全并不只有危险函数&#xff0c; 这只是冰山一角 。本文将介绍PHP从汇编层面到框架层面直到标准层面的所有攻击向量。 攻…

【H5】html实现微信授权登陆

html实现微信授权登陆前言网页授权的两种 scope 的区别开发指南第一步&#xff1a;用户同意授权&#xff0c;获取code第二步&#xff1a;通过 code 换取网页授权access_token第三步&#xff1a;拉取用户信息(需 scope 为 snsapi_userinfo)代码实现&#xff1a;效果图总结前言 …

用Python出了3000道数学题,外甥表示要正月剪头

人生苦短&#xff0c;快学Python&#xff01; 过年期间发现小外甥已经上小学了&#xff0c;我姐说老师今天给他们布置了寒假作业&#xff1a;每天坚持做乘法和加减法混合运算。 这我必须帮帮忙&#xff0c;用Python写了一段自动生成小学生计算题的代码&#xff0c;并支持导出…

Python入门之ChatGPT的API调(Python版)

一、Python环境部署 参考Python 环境搭建 | 菜鸟教程 Python官网&#xff1a;Welcome to Python.org Python文档下载地址&#xff1a;Our Documentation | Python.org 二、Thonny的安装 安装包地址&#xff1a;Thonny, Python IDE for beginners 三、ChatGPT的Key申请 网…

学Qt想系统的学习,看哪本书?

Qt 是一个跨平台应用开发框架&#xff08;framework&#xff09;&#xff0c;它是用 C语言写的一套类库。使用 Qt 能为 桌面计算机、服务器、移动设备甚至单片机开发各种应用&#xff08;application&#xff09;&#xff0c;特别是图形用户界面 &#xff08;graphical user in…

虹科分享|在ntopng中使用多用户模式

并非所有 ntop 用户都知道 ntopng 本机实现了多用户支持。也就是说&#xff0c;您可以使用ntopng收集和分析来自多个用户的流量&#xff0c;并向每个用户显示自己的流量&#xff0c;隐藏其余所有流量。 您需要做的就是非常简单&#xff1a; 1. 启动 ntopng 并将其配置为接收受…

Python将字典转换为csv

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

设计模式C++实现4:装饰模式

前言 参考大话设计模式&#xff1b; 详细内容参见大话模式一书第六章&#xff0c;该书使用C#实现&#xff0c;本实验通过C语言实现。 装饰模式&#xff08;Decorator&#xff09;&#xff0c;动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰…

MapReduce工作原理

一.MapReduce工作流程图 1、分片操作&#xff1a;FileInputstream&#xff0c;首先要计算切片大小&#xff0c;FileInputstream是一个抽象类&#xff0c;继承InputFormat接口&#xff0c;真正完成工作的是它的实现类&#xff0c;默认为是TextInputFormat&#xff0c;TextInputF…

docker一键部署网址导航+博客+管理系统(强势开源)

花森门户 在线地址(首次加载请耐心等待)&#xff1a;http://n.huasen.cc/ 码云仓库地址&#xff1a;https://gitee.com/HuaSenJioJio/huasenjio-compose Github仓库地址&#xff1a;https://github.com/huasenjio/huasenjio-compose huasenjio 系列网站增添新作品&#xff0c;&…

CSCCTF-2019-Qual-FlaskLight

网页里有提示 参数为search&#xff0c;GET传值 测试{{7*7}} 存在SSTI模板注入&#xff0c;在这里简单介绍python魔法函数&#xff0c;与Flask内置 __class__ 返回类型所属的对象 __mro__ 返回一个包含对象所继承的基类元组&#xff0c;方法在解析时按照元组的顺序解析。 __bas…

Dropout的深入理解(基础介绍、模型描述、原理深入、代码实现以及变种)

目录前言一、DropOut简介1-1、DropOut论文图解1-2、DropOut介绍1-3、DropOut产生动机1-4、DropOut流程简介二、模型描述2-1、公式描述2-2、神经网络图描述2-3、一些需要注意的问题&#xff01;三、Dropout代码实现以及相关变种&#xff08;部分有实现&#xff09;3-1、Dropout实…

Part 4 描述性统计分析(占比 10%)——上

文章目录【后续会持续更新CDA Level I&II备考相关内容&#xff0c;敬请期待】【考试大纲】【考试内容】【备考资料】1、统计基本概念1.1、统计学的含义及应用1.1.1、统计学的含义1.2.1、统计学的应用1.2、统计学的基本概念1.2.1、数据及数据的分类1.2.2、总体和样本1.2.3、…

体系结构原则

构建和设计软件解决方案时应考虑到可维护性。 本部分概述的原则可帮助指导你作出体系结构决策&#xff0c;生成简洁、可维护的应用程序。 一般而言&#xff0c;在这些原则的指导下构建的应用程序各部分间可通过显式接口或消息传送系统进行通信&#xff0c;并非松散耦合的离散组…

WinRAR自解压实现安装程序并开机自启

1、选择要打包的文件&#xff0c;右键添加到压缩文件&#xff0c;勾选“创建自解压格式压缩文件” 2、切换到高级&#xff0c;选择“自解压文件选项” 3、常规 - 指定解压缩路径 4、安装 - 解压缩后运行指定程序 5、模式 - 隐藏全部 全部显示&#xff1a;显示启动对话框&#…