可能很多朋友会觉得,前端其实是没有必要进行静态代码分析的,殊不知,往往一些关键点会出现在前端代码中,比如前后端交换加密的算法,以及一些接口的使用方法。
分析的源项目地址:
ps:是一个利用知识图谱构建知识库的开源项目,领域知识的构建。
针对上一篇中的开源项目,这一篇我们开始分析其前端部分的代码。
前端部分的代码在studio/webui下,打开目录,我们可以看到这样一个结构:
抛开Dockerfile和webui.go这样的构建打包文件不谈,这就是一个前端项目的标准结构。
构建前端调式环境
首先,需要了解的一个点是,这样项目的API结构究竟是如何调用的,这类前端工程化的项目一般都会全局配置代码,所以需要找到全局配置的文件。
这里应该是对不同的url前缀调用不同的接口,这里就要使用到我们之前搭建的远程服务器。
从代码来看,这里区分了以下几种前缀:
prefix | target | description |
---|---|---|
/api/builder | http://10.4.69.51 | 在注释里面有:http://10.2.174.230:6475 |
/api/studio | http://10.4.69.51 | http://10.2.174.230:6800 |
/api/engine | http://10.4.69.51 | http://10.2.174.230:6474 |
然后我们再翻看以下开源版本打开的docker情况:
发现刚好有注释中的几个端口,那么我们直接将该项目启动起来,target配置成我们在远端的地址。
同时上面的前缀也和我们的文档里面的描述一致
然后执行
yarn start
启动项目即可。
额,失败了。应该是改版了,还是改成只配置一个相同的。成功。
我们现在就构建起了整个前端调试的环境,即:前端使用本地,调用远程服务器端口。
分析前端结构
首先,assets是资源目录,里面包含了各类静态资源。
components是组件目录,页面即组件,组件是嵌套的。
download是要下载的文件,不过我认为这个部分其实可以放在后端,以接口的形式将下载流传给前端,否则每一次更新文件,都得重新拉取镜像,打包(考虑镜像成本)。
enums是一些枚举值;
hooks是拦截统一处理,以前在写web漏洞扫描器的时候,使用无头浏览器就需要对页面进行hook,注入相关的函数收集信息。
locales,我的理解应该是对后端字段的翻译,因为项目有中文和英文两种模式,而在这两种模式下对于同一个字段的不同描述是不同的,那么这里做的就是这个事儿。
pages,界面业务逻辑大多写在这个位置。
reduxConfig,redux组件的配置,redux我感觉有点像一个大缓存,里面根据组件+某些算法来生成键,进而维护组件的状态和动态属性。
services,统一维护调用的接口;
utils,一些工具类和方法。
获取URL
在进行繁杂的前端调试之前,也可以进行以下步骤,因为有接口文档,
但是大量的开源项目其实是没有接口文档的,那么我们就应该掌握分析接口的能力。
从上面的分析我们可以得到,services目录下的就是统一维护的接口。那么我们需要利用熟悉的语言编写解析程序,对代码进行结构化分析和关键信息提取。我这里就使用JAVA:
public class ReactProjectHandler {
public static Pattern pathPattern = Pattern.compile("`\\$(?<url>[\\/0-9a-zA-Z_]+)`");
public static void handleApiTs() {
String baseBuilder = "/api/builder/v1";
String baseEngine = "/api/engine/v1";
String baseStudio = "/api/studio/v1";
String fileName = "D:\\个人\\anydata\\kweaver\\studio\\webui\\src\\services\\api.ts";
List<String> a = FileUtils.getListKeyWithOneLine(fileName, false);
List<String> urls = new ArrayList<>();
for (String b : a) {
String c = StringFormatUtils.formatByName(b, new HashMap<String, Object>() {
{
put("baseBuilder", baseBuilder);
put("baseEngine", baseEngine);
put("baseStudio", baseStudio);
}
});
Matcher matcher = pathPattern.matcher(c);
if (matcher.find()){
String url = matcher.group("url");
urls.add(url);
}
}
Collections.sort(urls);
for (String url : urls){
FileUtils.appendFileWithRelativePath("anydata","apis.txt",url+"\n");
}
}
public static void main(String[] args) {
// String folderName = "";
// String ignores = ".less,test.js,test.tsx";
// FolderUtils.Dir dir = FolderUtils.getFolder(folderName, ignores);
handleAllApis();
}
}
这个程序将分析api.ts文件,并输出到结果文件中,那么我们收集的api就有如下内容:
/api/builder/v1/onto/ds
/api/builder/v1/onto/gettabbydsn
/api/builder/v1/onto/previewdata
/api/builder/v1/onto/dirlist
/api/builder/v1/onto/auto/autogenschema
/api/builder/v1/onto/getotl
/api/builder/v1/onto/getotlbyname
/api/builder/v1/onto/saveontology
/api/builder/v1/onto/modellist
/api/builder/v1/onto/
/api/builder/v1/graph/getdsbygraphid
/api/builder/v1/graph/
/api/builder/v1/onto/modelspo
/api/builder/v1/onto/getmodelotl
/api/builder/v1/onto/task/build_task
/api/builder/v1/onto/task/gettaskinfo
/api/builder/v1/onto/task/deletetask
/api/builder/v1/onto/task/get_task_files
/api/builder/v1/onto/task/deletealltask
/api/builder/v1/onto/updatename/
/api/builder/v1/onto/updateinfo/
/api/builder/v1/ds/testconnect
/api/builder/v1/ds
/api/builder/v1/ds/ds_copy
/api/builder/v1/ds
/api/builder/v1/graph/ds/
/api/builder/v1/ds/
/api/builder/v1/ds/delbydsids
/api/builder/v1/ds/searchbyname
/api/builder/v1/ds/Auth
/api/engine/v1/analysis
/api/engine/v1/explore/relation
/api/engine/v1/explore/expandv
/api/engine/v1/explore/path
/api/engine/v1/explore/pathDetail
/api/builder/v1/graph/output
/api/builder/v1/graph/input
/api/builder/v1/knw/get_all
/api/builder/v1/knw/get_by_name
/api/builder/v1/knw/network
/api/builder/v1/knw/edit_knw
/api/builder/v1/knw/delete_knw
/api/builder/v1/knw/get_graph_by_knw
/api/builder/v1/graph/info/onto
/api/builder/v1/graph/info/basic
/api/builder/v1/graph/info/count
/api/builder/v1/graph/info/detail
/api/engine/v1/properties
/api/builder/v1/onto/getbykgid
/api/studio/v1/graphdb
/api/studio/v1/graphdb/list
/api/studio/v1/graphdb/add
/api/studio/v1/graphdb/delete
/api/studio/v1/graphdb/update
/api/studio/v1/graphdb/test
/api/studio/v1/graphdb/graph/list
/api/studio/v1/opensearch/list
/api/studio/v1/opensearch
/api/studio/v1/opensearch/add
/api/studio/v1/opensearch/delete
/api/studio/v1/opensearch/update
/api/studio/v1/opensearch/test
/api/builder/v1/task
/api/builder/v1/task
/api/builder/v1/task/stoptask
/api/builder/v1/task
/api/builder/v1/task/get_progress
/api/builder/v1/graph/delbyids
/api/builder/v1/task
/api/builder/v1/timer
/api/builder/v1/timer/info
/api/builder/v1/timer/delete
/api/builder/v1/timer/add
/api/builder/v1/timer/update
/api/builder/v1/timer/switch
/api/builder/v1/graph
/api/builder/v1/graph
/api/builder/v1/graph
/api/builder/v1/graph/getbis
/api/builder/v1/graph/savenocheck
/api/builder/v1/graph/check_kmapinfo
/api/builder/v1/graph/graph_InfoExt/graphid
/api/studio/v1/swaggerDoc
/api/builder/v1/lexicon/getall
/api/builder/v1/lexicon/getbyid
/api/builder/v1/lexicon/create
/api/builder/v1/lexicon/labels
/api/builder/v1/lexicon/export
/api/builder/v1/lexicon/edit
/api/builder/v1/lexicon/delete
/api/builder/v1/lexicon/import_words
/api/builder/v1/lexicon/insert
/api/builder/v1/lexicon/search
/api/builder/v1/lexicon/edit_words
/api/builder/v1/lexicon/delete_words
/api/builder/v1/lexicon/template
/api/builder/v1/lexicon/word_cloud
/api/builder/v1/lexicon/word_cloud_search
我们来观察下代码:
可以发现这里其实有组装链接的情况,也就是说光分析api.ts,我们查看到的接口只是局部,无法看到所有东西,那么我们还需要考虑对这个目录下的js代码进行解析处理。
好了,吃午饭了。有空了再写。