全网最详细IDE插件开发之代码审计
字数 2316 2025-08-15 21:33:46

IntelliJ IDEA 插件开发与代码审计工具实现教程

一、背景与概述

本教程将详细介绍如何开发一个IntelliJ IDEA插件,特别是针对代码审计功能的插件开发。教程基于陌陌安全团队开源的momo-code-sec-inspector-java项目,从环境搭建到实际插件开发,逐步讲解整个过程。

二、开发环境搭建

2.1 准备工作

序号 软件名 备注
1 IntelliJ IDEA 2020.1.4 Community 下载页面
2 JDK 1.8 百度云链接(密码:9k19)
3 momo开源代码 git clone地址

2.2 JDK安装

  1. 下载JDK 1.8安装包
  2. 使用"下一步"方式完成安装
  3. 确保环境变量配置正确

2.3 IDEA安装与项目创建

  1. 安装IntelliJ IDEA Community版,使用默认设置
  2. 创建新项目:
    • 选择Gradle作为项目构建工具
    • 勾选"IntelliJ Platform Plugin"选项
    • 确保Project SDK自动选择为JDK 1.8
  3. 填写项目基本信息:
    • GroupId: com.security.guy
    • ArtifactId: myfirstPlugin
    • Version: 1.0-SNAPSHOT
  4. 等待Gradle构建项目框架(可能需要10-30分钟下载依赖)

2.4 项目结构详解

项目根目录/
├── build.gradle            # Gradle配置文件
├── gradlew                 # Linux下Gradle执行文件
├── gradlew.bat             # Windows下Gradle执行文件
├── settings.gradle         # Gradle设置文件
├── .gradle/                # Gradle缓存目录
│   ├── 6.1.1/              # Gradle版本目录
│   │   ├── fileChanges/    # 文件变更记录
│   │   ├── fileHashes/     # 文件哈希值
│   │   └── ...             # 其他Gradle缓存文件
├── .idea/                  # IDEA项目配置
│   ├── compiler.xml        # 编译器配置
│   ├── gradle.xml          # Gradle配置
│   └── ...                 # 其他IDEA配置文件
├── gradle/                 # Gradle包装器
│   ├── wrapper/
│   │   ├── gradle-wrapper.jar
│   │   └── gradle-wrapper.properties
└── src/                    # 源代码目录
    ├── main/               # 主代码
    │   ├── java/           # Java源代码
    │   └── resources/      # 资源文件
    │       ├── META-INF/   # 插件元信息
    │       │   └── plugin.xml # 插件配置文件
    └── test/               # 测试代码
        ├── java/           # 测试Java代码
        └── resources/      # 测试资源

三、开发第一个插件

3.1 组件类型介绍

组件类型 描述 对应plugin.xml配置元素
ApplicationComponent 在IDEA启动时初始化,整个IDEA只有一个实例 <application-components>
ProjectComponent IDEA会为每一个Project实例创建对应级别的Component <project-components>
ModuleComponent IDEA会为每一个已加载Project中的每一个模块(module)创建对应级别的Component <module-components>

3.2 创建启动弹窗插件

1. 创建ApplicationComponent

src/main/java下创建包com.tolly.security.action,然后创建MyChickenSoul.java

package com.tolly.security.action;

import com.intellij.openapi.application.Application;
import com.intellij.openapi.components.ApplicationComponent;

public class MyChickenSoul implements ApplicationComponent {
    @Override
    public void initComponent() {
        // 创建并显示对话框
        DialogChickenSoul dialogChickenSoul = new DialogChickenSoul();
        dialogChickenSoul.show();
    }
}

2. 创建对话框类

在相同包下创建DialogChickenSoul.java

package com.tolly.security.action;

import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;

public class DialogChickenSoul extends DialogWrapper {
    protected DialogChickenSoul() {
        super(true);
        setTitle("哈哈");  // 设置对话框标题
        init();  // 必须调用初始化方法
    }

    @Override
    protected @Nullable JComponent createCenterPanel() {
        JPanel jPanel = new JPanel();
        HttpRequest hrequest = new HttpRequest();
        String content = hrequest.httpclient();  // 获取网络内容
        JLabel jLabel = new JLabel(content);
        jPanel.add(jLabel);
        return jPanel;
    }
}

3. 创建HTTP请求工具类

创建HttpRequest.java用于获取网络内容:

package com.tolly.security.action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;

public class HttpRequest {
    public String httpclient() {
        String url = "https://data.zhai78.com/openOneGood.php";
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        
        try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
            HttpEntity httpEntity = httpResponse.getEntity();
            String response = EntityUtils.toString(httpEntity);
            JSONObject result = JSON.parseObject(response);
            return result.getString("txt");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
            return "请求失败";
        } catch (IOException e) {
            e.printStackTrace();
            return "IO异常";
        }
    }
}

4. 添加依赖

修改build.gradle文件,添加必要的依赖:

plugins {
    id 'java'
    id 'org.jetbrains.intellij' version '0.6.5'
}

group 'com.security.guy'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    // 添加HTTPClient和FastJSON依赖
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13'
    compile group: 'com.alibaba', name: 'fastjson', version: '1.2.75'
}

intellij {
    version '2020.1.4'
}

patchPluginXml {
    changeNotes """
      Add change notes here.<br>
      <em>most HTML tags may be used</em>
    """
}

// 解决中文乱码问题
tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
}

5. 配置plugin.xml

修改src/main/resources/META-INF/plugin.xml文件:

<idea-plugin>
    <id>com.security.guy.myfirstPlugin</id>
    <name>Plugin display name here</name>
    <vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
    <description><![CDATA[
        Enter short description for your plugin here.<br>
        <em>most HTML tags may be used</em>
    ]]></description>
    
    <depends>com.intellij.modules.platform</depends>
    
    <extensions defaultExtensionNs="com.intellij">
        <!-- 可以在此添加扩展点 -->
    </extensions>
    
    <actions>
        <!-- 可以在此添加动作 -->
    </actions>
    
    <application-components>
        <component>
            <implementation-class>com.tolly.security.action.MyChickenSoul</implementation-class>
        </component>
    </application-components>
</idea-plugin>

6. 运行插件

  1. 点击Gradle工具栏中的runIde任务
  2. 等待IDEA沙箱启动
  3. 观察启动时是否弹出包含网络内容的对话框

四、代码审计插件开发进阶

4.1 理解SAST原理

静态应用程序安全测试(SAST)通过分析源代码而不执行程序来发现潜在安全问题。在IDE插件中实现SAST可以:

  1. 实时分析代码
  2. 标记潜在安全问题
  3. 提供修复建议
  4. 与开发流程无缝集成

4.2 实现代码审计功能

1. 创建代码检查器

public class SecurityInspector extends LocalInspectionTool {
    @Nullable
    @Override
    public ProblemDescriptor[] checkFile(@NotNull PsiFile file, 
                                       @NotNull InspectionManager manager, 
                                       boolean isOnTheFly) {
        // 实现安全检查逻辑
        List<ProblemDescriptor> problems = new ArrayList<>();
        
        // 示例:检查SQL注入
        checkSqlInjection(file, manager, problems);
        
        return problems.toArray(new ProblemDescriptor[0]);
    }
    
    private void checkSqlInjection(PsiFile file, 
                                 InspectionManager manager,
                                 List<ProblemDescriptor> problems) {
        // 查找所有字符串拼接的SQL语句
        file.accept(new JavaRecursiveElementVisitor() {
            @Override
            public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                super.visitMethodCallExpression(expression);
                
                if (isSqlExecutionMethod(expression)) {
                    PsiExpression[] args = expression.getArgumentList().getExpressions();
                    if (args.length > 0 && isStringConcatenation(args[0])) {
                        // 创建问题描述
                        ProblemDescriptor descriptor = manager.createProblemDescriptor(
                            expression,
                            "Potential SQL injection vulnerability",
                            (LocalQuickFix)null,
                            ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
                            isOnTheFly
                        );
                        problems.add(descriptor);
                    }
                }
            }
        });
    }
}

2. 注册检查器

plugin.xml中添加:

<extensions defaultExtensionNs="com.intellij">
    <localInspection 
        language="JAVA"
        displayName="Security Inspector"
        groupPath="Java"
        enabledByDefault="true"
        level="ERROR"
        implementationClass="com.tolly.security.inspector.SecurityInspector"/>
</extensions>

3. 实现复杂规则

public class XssInspector extends LocalInspectionTool {
    @Nullable
    @Override
    public ProblemDescriptor[] checkFile(@NotNull PsiFile file, 
                                       @NotNull InspectionManager manager, 
                                       boolean isOnTheFly) {
        List<ProblemDescriptor> problems = new ArrayList<>();
        
        file.accept(new JavaRecursiveElementVisitor() {
            @Override
            public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                super.visitMethodCallExpression(expression);
                
                // 检查未转义的输出到响应的方法
                if (isResponseWriteMethod(expression)) {
                    PsiExpression[] args = expression.getArgumentList().getExpressions();
                    if (args.length > 0 && isUnescapedOutput(args[0])) {
                        problems.add(createProblem(manager, expression, 
                            "Potential XSS vulnerability: unescaped output to response"));
                    }
                }
            }
        });
        
        return problems.toArray(new ProblemDescriptor[0]);
    }
}

五、插件打包与发布

5.1 打包插件

  1. 在Gradle面板中运行buildPlugin任务
  2. 生成的插件包位于build/distributions目录
  3. 文件格式为.zip.jar

5.2 发布到JetBrains插件市场

  1. 注册JetBrains账号
  2. 申请成为插件开发者
  3. 通过JetBrains Plugin Repository上传插件
  4. 填写插件元数据:
    • 描述
    • 截图
    • 变更日志
    • 兼容性信息

六、调试与优化

6.1 调试技巧

  1. 使用IDEA内置调试器
  2. 设置断点在关键检查逻辑
  3. 观察PSI树结构
  4. 使用PsiViewer插件查看PSI结构

6.2 性能优化

  1. 避免全文件扫描,针对特定元素检查
  2. 缓存常用查询结果
  3. 使用轻量级检查器
  4. 考虑延迟加载规则

七、总结

本教程详细介绍了从零开始开发IntelliJ IDEA插件的过程,特别是针对代码审计功能的实现。关键点包括:

  1. 正确搭建开发环境
  2. 理解IDEA插件架构
  3. 实现各种类型的组件
  4. 开发自定义代码检查器
  5. 打包和发布插件

通过本教程,您应该能够开发出自己的代码审计插件,或基于陌陌安全开源的SAST规则进行二次开发。

IntelliJ IDEA 插件开发与代码审计工具实现教程 一、背景与概述 本教程将详细介绍如何开发一个IntelliJ IDEA插件,特别是针对代码审计功能的插件开发。教程基于陌陌安全团队开源的 momo-code-sec-inspector-java 项目,从环境搭建到实际插件开发,逐步讲解整个过程。 二、开发环境搭建 2.1 准备工作 | 序号 | 软件名 | 备注 | |------|---------------------------|------| | 1 | IntelliJ IDEA 2020.1.4 Community | 下载页面 | | 2 | JDK 1.8 | 百度云链接(密码:9k19) | | 3 | momo开源代码 | git clone地址 | 2.2 JDK安装 下载JDK 1.8安装包 使用"下一步"方式完成安装 确保环境变量配置正确 2.3 IDEA安装与项目创建 安装IntelliJ IDEA Community版,使用默认设置 创建新项目: 选择Gradle作为项目构建工具 勾选"IntelliJ Platform Plugin"选项 确保Project SDK自动选择为JDK 1.8 填写项目基本信息: GroupId: com.security.guy ArtifactId: myfirstPlugin Version: 1.0-SNAPSHOT 等待Gradle构建项目框架(可能需要10-30分钟下载依赖) 2.4 项目结构详解 三、开发第一个插件 3.1 组件类型介绍 | 组件类型 | 描述 | 对应plugin.xml配置元素 | |--------------------|----------------------------------------------------------------------|-----------------------------| | ApplicationComponent | 在IDEA启动时初始化,整个IDEA只有一个实例 | <application-components> | | ProjectComponent | IDEA会为每一个Project实例创建对应级别的Component | <project-components> | | ModuleComponent | IDEA会为每一个已加载Project中的每一个模块(module)创建对应级别的Component | <module-components> | 3.2 创建启动弹窗插件 1. 创建ApplicationComponent 在 src/main/java 下创建包 com.tolly.security.action ,然后创建 MyChickenSoul.java : 2. 创建对话框类 在相同包下创建 DialogChickenSoul.java : 3. 创建HTTP请求工具类 创建 HttpRequest.java 用于获取网络内容: 4. 添加依赖 修改 build.gradle 文件,添加必要的依赖: 5. 配置plugin.xml 修改 src/main/resources/META-INF/plugin.xml 文件: 6. 运行插件 点击Gradle工具栏中的 runIde 任务 等待IDEA沙箱启动 观察启动时是否弹出包含网络内容的对话框 四、代码审计插件开发进阶 4.1 理解SAST原理 静态应用程序安全测试(SAST)通过分析源代码而不执行程序来发现潜在安全问题。在IDE插件中实现SAST可以: 实时分析代码 标记潜在安全问题 提供修复建议 与开发流程无缝集成 4.2 实现代码审计功能 1. 创建代码检查器 2. 注册检查器 在 plugin.xml 中添加: 3. 实现复杂规则 五、插件打包与发布 5.1 打包插件 在Gradle面板中运行 buildPlugin 任务 生成的插件包位于 build/distributions 目录 文件格式为 .zip 或 .jar 5.2 发布到JetBrains插件市场 注册JetBrains账号 申请成为插件开发者 通过JetBrains Plugin Repository上传插件 填写插件元数据: 描述 截图 变更日志 兼容性信息 六、调试与优化 6.1 调试技巧 使用IDEA内置调试器 设置断点在关键检查逻辑 观察PSI树结构 使用 PsiViewer 插件查看PSI结构 6.2 性能优化 避免全文件扫描,针对特定元素检查 缓存常用查询结果 使用轻量级检查器 考虑延迟加载规则 七、总结 本教程详细介绍了从零开始开发IntelliJ IDEA插件的过程,特别是针对代码审计功能的实现。关键点包括: 正确搭建开发环境 理解IDEA插件架构 实现各种类型的组件 开发自定义代码检查器 打包和发布插件 通过本教程,您应该能够开发出自己的代码审计插件,或基于陌陌安全开源的SAST规则进行二次开发。